From: Giovanni Meo Date: Fri, 22 Mar 2013 11:46:02 +0000 (+0100) Subject: Initial opendaylight infrastructure commit!! X-Git-Tag: releasepom-0.1.0~635 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=42210c03b0a4c54706320ba9f55794c0abd4d201 Initial opendaylight infrastructure commit!! Change-Id: I2f6610f89c8c32dc6dab4e6982ce06a9b038a85a Signed-off-by: Giovanni Meo --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..f1f8a6ef9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.class +**/target +**/bin +dist +**/logs +products +repository +workspace +*~ +target +.classpath +.project +.settings diff --git a/README.OPENDAYLIGHT b/README.OPENDAYLIGHT new file mode 100644 index 0000000000..91659801b6 --- /dev/null +++ b/README.OPENDAYLIGHT @@ -0,0 +1,34 @@ +DIRECTORY ORGANIZATION +====================== +- third-party: contains all the third-party artifacts than needed +repackaging or needed code modifications. +- third-party/commons: contains all the parent POM files for the +projects under the third-party directory. Only one is expected, which +is the one located under third-party/commons/third-party, but there is +a directory just in case we need to host more with different +variations. +- opendaylight: contains all the artifacts that constitute the +controller project. +- opendaylight/distribution: contains all the distributions that can +be generated by packaging the several artifact. In practice for now +there are two: + - "opendaylight", which is the full distribution of the controller + - "sdk", which contains only the artifact needed to build an app + against the controller (beaware this is still incomplete) +The idea of the distribution directory is that more distribution can +be added at will, maybe just composing subsets of the whole controller +artifact set. + +HOW TO BUILD +============ +In order to build it's required to have JDK 1.7+ and Maven 3+, to get +a build going it's needed to: +1) Choose the distribution, from within opendaylight/distribution +2) Go in the directory and run + "mvn clean install" +3) On succesfull completion go in the target directory to pick the zip +file of the distribution or controller can be executed right from +there going into the distribution directory. + +Thanks!! + diff --git a/opendaylight/clustering/services/pom.xml b/opendaylight/clustering/services/pom.xml new file mode 100644 index 0000000000..a5e09fa59e --- /dev/null +++ b/opendaylight/clustering/services/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.opendaylight.controller.clustering.services + + + javax.transaction + + + + + + + diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheConfigException.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheConfigException.java new file mode 100644 index 0000000000..98e5695e3f --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheConfigException.java @@ -0,0 +1,36 @@ + +/* + * 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 + */ + +/** + * @file CacheConfigException.java + * + * @brief Describe an exception that is raised when the cache being + * allocated has configuration errors, like mismatch parameters are + * passed and so on. + * + * + */ +package org.opendaylight.controller.clustering.services; + +import java.lang.Exception; + +/** + * Describe an exception that is raised when the cache being + * allocated has configuration errors, like mismatch parameters are + * passed and so on. + */ +public class CacheConfigException extends Exception { + + /** + * Instantiates a new cache config exception. + */ + public CacheConfigException() { + super(); + } +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheExistException.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheExistException.java new file mode 100644 index 0000000000..21bf700321 --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheExistException.java @@ -0,0 +1,34 @@ + +/* + * 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 + */ + +/** + * @file CacheExistException.java + * + * @brief Describe an exception that is raised when the cache being + * allocated already exists + * + * + */ +package org.opendaylight.controller.clustering.services; + +import java.lang.Exception; + +/** + * Describe an exception that is raised when the cache being + * allocated already exists + */ +public class CacheExistException extends Exception { + + /** + * Instantiates a new cache exist exception. + */ + public CacheExistException() { + super(); + } +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheListenerAddException.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheListenerAddException.java new file mode 100644 index 0000000000..f171e9ce00 --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheListenerAddException.java @@ -0,0 +1,33 @@ + +/* + * 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 + */ + +/** + * @file CacheListenerAddException.java + * + * @brief Describe an exception that is raised when the cache + * Listener being added fails for any reason + * + */ +package org.opendaylight.controller.clustering.services; + +import java.lang.Exception; + +/** + * Describe an exception that is raised when the cache + * Listener being added fails for any reason + */ +public class CacheListenerAddException extends Exception { + + /** + * Instantiates a new cache listener add exception. + */ + public CacheListenerAddException() { + super(); + } +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ICacheUpdateAware.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ICacheUpdateAware.java new file mode 100644 index 0000000000..187309ba82 --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ICacheUpdateAware.java @@ -0,0 +1,67 @@ + +/* + * 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 + */ + +/** + * @file ICacheUpdateAware.java + * + * @brief Interface for getting clustered cache updates + * + * Interface that needs to be implemented by the components + * that want to be informed of an update in a Clustered Cache. The + * interface need to be registerd in the OSGi service registry with a + * property "cachenames" which will contains a PropertySet object + * listing all the caches for which their is interes. + */ +package org.opendaylight.controller.clustering.services; + +/** + * Interface that needs to be implemented by the components + * that want to be informed of an update in a Clustered Cache. The + * interface need to be registerd in the OSGi service registry with a + * property "cachenames" which will contains a PropertySet object + * listing all the caches for which their is interes. + * + */ +public interface ICacheUpdateAware { + /** + * Invoked when a new entry is available in the cache, the key is + * only provided, the value will come as an entryUpdate invocation + * + * @param key Key for the entry just created + * @param cacheName name of the cache for which update has been + * received + * @param originLocal true if the event is generated from this + * node + */ + void entryCreated(K key, String cacheName, boolean originLocal); + + /** + * Called anytime a given entry is updated + * + * @param key Key for the entry modified + * @param new_value the new value the key will have + * @param cacheName name of the cache for which update has been + * received + * @param originLocal true if the event is generated from this + * node + */ + void entryUpdated(K key, V new_value, String cacheName, boolean originLocal); + + /** + * Called anytime a given key is removed from the + * ConcurrentHashMap we are listening to. + * + * @param key Key of the entry removed + * @param cacheName name of the cache for which update has been + * received + * @param originLocal true if the event is generated from this + * node + */ + void entryDeleted(K key, String cacheName, boolean originLocal); +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterContainerServices.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterContainerServices.java new file mode 100644 index 0000000000..f0d6d7e40f --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterContainerServices.java @@ -0,0 +1,30 @@ + +/* + * 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 + */ + +/** + * @file IClusterContainerServices.java + * + * @brief : Set of services and application will expect from the + * clustering services provider. This interface is per-container and so + * the container parameter is implicitely known + * + * Contract between the applications and the clustering service + * providers. Container version + */ + +package org.opendaylight.controller.clustering.services; + +/** + * Set of services and application will expect from the + * clustering services provider. This interface is per-container and so + * the container parameter is implicitely known + * + */ +public interface IClusterContainerServices extends IClusterServicesCommon { +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterGlobalServices.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterGlobalServices.java new file mode 100644 index 0000000000..61ad41529d --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterGlobalServices.java @@ -0,0 +1,30 @@ + +/* + * 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 + */ + +/** + * @file IClusterGlobalServices.java + * + * @brief : Set of services and application will expect from the + * clustering services provider. This interface is supposed to have + * Global scope + * + * Contract between the applications and the clustering service + * providers. Global version + */ + +package org.opendaylight.controller.clustering.services; + +/** + * Set of services and application will expect from the + * clustering services provider. This interface is supposed to have + * Global scope + * + */ +public interface IClusterGlobalServices extends IClusterServicesCommon { +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServices.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServices.java new file mode 100644 index 0000000000..031434f8e8 --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServices.java @@ -0,0 +1,285 @@ + +/* + * 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 + */ + +/** + * @file IClusterServices.java + * + * @brief : Set of services and application will expect from the + * clustering services provider + * + * Contract between the applications and the clustering service + * providers. + */ + +package org.opendaylight.controller.clustering.services; + +import java.net.InetAddress; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.Transaction; + +/** + * Set of services and application will expect from the + * clustering services provider + * + */ +public interface IClusterServices { + + /** + * Enumeration of the several modality with which a + * ConcurrentHashMap cache can be requested to the clustering + * services. The property that can be requested can be multiple. + * + */ + public enum cacheMode { + /** + * Set for a cache that supports transaction that implies that + * is a transaction is open on the current thread the data + * will not immediately be reflected in the cache but will be + * staged till commit or rollback. If the transaction if NOT + * open the data will immediately go in the cache without + * staging. + */ + TRANSACTIONAL, + /** + * Set on a cache that doesn't want to support + * transaction, so irrespective of the fact that we are in + * the middle of a transaction or no data will be + * immediately committed in the cache. + * + */ + NON_TRANSACTIONAL; + } + + /** + * Enumeration of the several properties that a cache can carry + * + */ + public enum cacheProps { + /** + * The property returned describe the caracteristics of the + * transaction setup for the cache it was retrieved. + */ + TRANSACTION_PROP, + /** + * The property returned report the clustering + * caracteristics of the cache for which property was + * queried. + */ + CLUSTERING_PROP, + /** + * The property returned reports the locking + * caracteristics of the cache for which the property was + * queried + */ + LOCKING_PROP; + } + + /** + * Method that will create a new named cache per-container. The data + * structure if already present will cause an exception to be + * thrown to the caller. + * + * @param containerName Container to which the datastructure is associated + * @param cacheName Name of the ConcurrentHashMap to create + * @param cMode Mode of the cache that need to be retrieved. This + * is a set such that more than one property can be provided, of + * course contrasting requirements will not be accepted and in + * that case an exception is thrown + * + * @return ConcurrentHashMap to be used to modify the data structure + */ + ConcurrentMap createCache(String containerName, String cacheName, + Set cMode) throws CacheExistException, + CacheConfigException; + + /** + * Method that will retrieve and return the handle to modify a + * data structire distributed via clustering services. The + * datastructure shall already have been created else a null + * reference will be returned. + * + * @param containerName Container to which the datastructure is associated + * @param cacheName Name of the ConcurrentHashMap to retrieve + * + * @return ConcurrentHashMap to be used to modify the data structure + */ + ConcurrentMap getCache(String containerName, String cacheName); + + /** + * Destroy a cachename given containerName/cachename, if doesn't exist + * the function does nothing. If the datastructure exists, the + * whole cluster will destroy the instance + * + * @param containerName Container to which the datastructure is associated + * @param cacheName Name of the ConcurrentHashMap to destroy + */ + void destroyCache(String containerName, String cacheName); + + /** + * Function to test the existance of a cache with a given name already + * + * @param containerName Container to which the datastructure is associated + * @param cacheName Name of the ConcurrentHashMap to destroy + * + * @return true if exists already, false otherwise + */ + boolean existCache(String containerName, String cacheName); + + /** + * Return the list of all teh caches registered with a container + * + * @param containerName Container for which we want to list all the caches registered + * + * @return The set of names, expressed as strings + */ + Set getCacheList(String containerName); + + /** + * Return a list of properties that caracterize the cache + * + * @param containerName Name of the container where data structure resides + * @param cacheName Name of the cache + * + * @return The list of properties related to the cache + */ + Properties getCacheProperties(String containerName, String cacheName); + + /** + * Register an update handler for a given containerName/cacheName + * shared data structure. Multiple listeners are possible. + * + * @param containerName Container to which the datastructure is associated + * @param cacheName Name of the ConcurrentHashMap for which we + * want to register the listener + * @param u Interface to invoke when the updates are received + */ + void addListener(String containerName, String cacheName, IGetUpdates u) + throws CacheListenerAddException; + + /** + * Return a set of interfaces that are interesteed to listen to + * updates coming for a given datastructure shared via clustering + * services. + * + * @param containerName Container to which the datastructure is associated + * @param cacheName Name of the ConcurrentHashMap for which we + * want to retrieve the listener + */ + Set> getListeners(String containerName, String cacheName); + + /** + * UN-Register an update handler for a given containerName/cacheName + * shared data structure. Multiple listeners are possible. + * + * @param containerName Container to which the datastructure is associated + * @param cacheName Name of the ConcurrentHashMap for which we + * want to un-register the listener + * @param u Interface to un-register + */ + void removeListener(String containerName, String cacheName, + IGetUpdates u); + + /** + * Begin a transaction covering with all the data structures/HW + * updates. One transaction per-thread can be opened at the + * most, that means if multiple thread are available, multiple + * transactions can be outstanding. + * + */ + void tbegin() throws NotSupportedException, SystemException; + + /** + * Commit a transaction covering all the data structures/HW updates. + */ + void tcommit() throws RollbackException, HeuristicMixedException, + HeuristicRollbackException, java.lang.SecurityException, + java.lang.IllegalStateException, SystemException; + + /** + * Rollback a transaction covering all the data structures/HW updates + */ + void trollback() throws java.lang.IllegalStateException, + java.lang.SecurityException, SystemException; + + /** + * Return the javax.transaction.Transaction associated with this thread + * + * + * @return Return the current transaction associated with this thread + */ + Transaction tgetTransaction() throws SystemException; + + /** + * @deprecated + * Function that says if we are standby in the 1-1 redundancy with + * active/standby model. The API is not encouraged hence is + * deprecated. It is supposed to be used as a stop-gap till the + * active-standby goal is achieved. The only guys that are + * supposed to use are: + * - southbound layer, should not listen on the OF port if standby + * - jetty configuration, on standby jetty should redirect calls + * to the active. + * + * @return true if the role is the one of standby, else false + */ + boolean amIStandby(); + + /** + * @deprecated + * Get the InetAddress of the active controller for the + * active-standby case, where the standby controller has to + * redirect the HTTP requests received from applications layer + * + * @return Address of the active controller + */ + InetAddress getActiveAddress(); + + /** + * Get the InetAddress of the all the controllers that make up this + * Cluster + * + * @return List of InetAddress'es of all the controllers + */ + List getClusteredControllers(); + + /** + * Get the InetAddress of this Controller as seen by the Cluster Manager + * + * @return InetAddress of this Controller as seen by the Cluster Manager. + */ + InetAddress getMyAddress(); + + /** + * @deprecated + * Register a listener to the event of ChangeRole, raised every + * time there is a change in the role of active or standby. + * + * @param i Interface that will be called when the Role Change happens + */ + void listenRoleChange(IListenRoleChange i) + throws ListenRoleChangeAddException; + + /** + * @deprecated + * UN-Register a listener to the event of ChangeRole, raised every + * time there is a change in the role of active or standby. + * + * @param i Interface that will be called when the Role Change happens + */ + void unlistenRoleChange(IListenRoleChange i); +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServicesCommon.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServicesCommon.java new file mode 100644 index 0000000000..e292f73e54 --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IClusterServicesCommon.java @@ -0,0 +1,178 @@ + +/* + * 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 + */ + +/** + * @file IClusterServicesCommon.java + * + * @brief : Set of services and application will expect from the + * clustering services provider. This interface is going to be the + * base for per-container and Global services and so the container + * parameter is omitted but who uses knows about it + * + * Contract between the applications and the clustering service + * providers. Common version + */ + +package org.opendaylight.controller.clustering.services; + +import java.net.InetAddress; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.Transaction; + +/** + * @deprecated for internal use + * Set of services and application will expect from the + * clustering services provider. This interface is going to be the + * base for per-container and Global services and so the container + * parameter is omitted but who uses knows about it + * + */ +public interface IClusterServicesCommon { + /** + * Method that will create a new named cache. The data + * structure if already present will cause an exception to be + * thrown to the caller. + * + * @param cacheName Name of the ConcurrentHashMap to create + * @param cMode Mode of the cache that need to be retrieved. This + * is a set such that more than one property can be provided, of + * course contrasting requirements will not be accepted and in + * that case an exception is thrown + * + * @return ConcurrentHashMap to be used to modify the data structure + */ + ConcurrentMap createCache(String cacheName, + Set cMode) throws CacheExistException, + CacheConfigException; + + /** + * Method that will retrieve and return the handle to modify a + * data structire distributed via clustering services. The + * datastructure shall already have been created else a null + * reference will be returned. + * + * @param cacheName Name of the ConcurrentHashMap to retrieve + * + * @return ConcurrentHashMap to be used to modify the data structure + */ + ConcurrentMap getCache(String cacheName); + + /** + * Destroy a cachename given cachename, if doesn't exist + * the function does nothing. If the datastructure exists, the + * whole cluster will destroy the instance + * + * @param cacheName Name of the ConcurrentHashMap to destroy + */ + void destroyCache(String cacheName); + + /** + * Function to test the existance of a cache with a given name already + * + * @param cacheName Name of the ConcurrentHashMap to destroy + * + * @return true if exists already, false otherwise + */ + boolean existCache(String cacheName); + + /** + * Return the list of all teh caches registered in the context of + * the called + * + * + * @return The set of names, expressed as strings + */ + Set getCacheList(); + + /** + * Return a list of properties that caracterize the cache + * + * @param cacheName Name of the cache + * + * @return The list of properties related to the cache + */ + Properties getCacheProperties(String cacheName); + + /** + * Begin a transaction covering with all the data structures/HW + * updates. One transaction per-thread can be opened at the + * most, that means if multiple thread are available, multiple + * transactions can be outstanding. + * + */ + void tbegin() throws NotSupportedException, SystemException; + + /** + * Commit a transaction covering all the data structures/HW updates. + */ + void tcommit() throws RollbackException, HeuristicMixedException, + HeuristicRollbackException, java.lang.SecurityException, + java.lang.IllegalStateException, SystemException; + + /** + * Rollback a transaction covering all the data structures/HW updates + */ + void trollback() throws java.lang.IllegalStateException, + java.lang.SecurityException, SystemException; + + /** + * Return the javax.transaction.Transaction associated with this thread + * + * + * @return Return the current transaction associated with this thread + */ + Transaction tgetTransaction() throws SystemException; + + /** + * + * Get the InetAddress of the coordinator controller in the cluster + * + * @return Address of the coordinator controller + */ + InetAddress getCoordinatorAddress(); + + /** + * Get the InetAddress of the all the controllers that make up this + * Cluster + * + * @return List of InetAddress'es of all the controllers + */ + List getClusteredControllers(); + + /** + * Get the InetAddress of this Controller as seen by the Cluster Manager + * + * @return InetAddress of this Controller as seen by the Cluster Manager. + */ + InetAddress getMyAddress(); + + /** + * Function that is used to know if the node on which is called is + * the cluster coordinator. The API is useful in scenario where + * the same logic is not worthed to be replicated on multiple + * nodes in the cluster and one can cook it up for all the + * others. In this scenario running the logic on the coordinator + * make sense, this of course implies logics that are not heavy + * and don't need to be scaled out linearly with the size of the + * cluster. + * + * @return true if the node on which the API is called is the + * coordinator for the cluster + */ + boolean amICoordinator(); +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ICoordinatorChangeAware.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ICoordinatorChangeAware.java new file mode 100644 index 0000000000..4a92aca604 --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ICoordinatorChangeAware.java @@ -0,0 +1,32 @@ + +/* + * 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 + */ + +/** + * @file ICoordinatorChangeAware.java + * + * + * @brief Interface that needs to be implemented by who wants to be + * notified of coordinator role change + * + */ +package org.opendaylight.controller.clustering.services; + +/** + * Interface that needs to be implemented by who wants to be + * notified of coordinator role change + * + */ +public interface ICoordinatorChangeAware { + + /** + * Function that will be called when there is the event of + * coordinator change in the cluster. + */ + public void coordinatorChanged(); +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IGetUpdates.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IGetUpdates.java new file mode 100644 index 0000000000..1f9a45a249 --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IGetUpdates.java @@ -0,0 +1,59 @@ + +/* + * 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 + */ + +/** + * @file IGetUpdates.java + * + * @brief Interface that needs to be implemented by the listeners of + * updates received on data structure shared in the cluster + * + * Interface that needs to be implemented by the listeners of updates + * received on data structure shared in the cluster + */ +package org.opendaylight.controller.clustering.services; + +/** + * @deprecated for internal use + * Interface that needs to be implemented by the listeners of + * updates received on data structure shared in the cluster + */ +public interface IGetUpdates { + /** + * Invoked when a new entry is available in the cache, the key is + * only provided, the value will come as an entryUpdate invocation + * + * @param key Key for the entry just created + * @param containerName container for which the update has been received + * @param cacheName name of the cache for which update has been received + */ + void entryCreated(K key, String containerName, String cacheName, + boolean local); + + /** + * Called anytime a given entry is updated + * + * @param key Key for the entry modified + * @param new_value the new value the key will have + * @param containerName container for which the update has been received + * @param cacheName name of the cache for which update has been received + */ + void entryUpdated(K key, V new_value, String containerName, + String cacheName, boolean local); + + /** + * Called anytime a given key is removed from the + * ConcurrentHashMap we are listening to. + * + * @param key Key of the entry removed + * @param containerName container for which the update has been received + * @param cacheName name of the cache for which update has been received + */ + void entryDeleted(K key, String containerName, String cacheName, + boolean originLocal); +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IListenRoleChange.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IListenRoleChange.java new file mode 100644 index 0000000000..e5c7a8839e --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/IListenRoleChange.java @@ -0,0 +1,41 @@ + +/* + * 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 + */ + +/** + * @file IListenRoleChange.java + * + * + * @brief Interface that needs to be implemented by who wants to be + * notified of new active change + * + * @deprecated + * + * Interface that needs to be implemented by who wants to be notified + * of newly active taking over. Interface that is supposed to be + * short-lived and will be removed as soon as active-standby goal is reached. + */ +package org.opendaylight.controller.clustering.services; + +/** + * Interface that needs to be implemented by who wants to be notified + * of newly active taking over. Interface that is supposed to be + * short-lived and will be removed as soon as active-standby goal is reached. + * + */ +public interface IListenRoleChange { + + /** + * @deprecated + * Function that will be called when a new active is + * available. This function is supposed only to be of use till + * active-standby milestone is reached, after will be removed. + * + */ + public void newActiveAvailable(); +} diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ListenRoleChangeAddException.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ListenRoleChangeAddException.java new file mode 100644 index 0000000000..ad6cd2eddd --- /dev/null +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ListenRoleChangeAddException.java @@ -0,0 +1,33 @@ + +/* + * 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 + */ + +/** + * @file ListenRoleChangeAddException.java + * + * @brief Describe an exception that is raised when the cache + * Listener being added fails for any reason + * + */ +package org.opendaylight.controller.clustering.services; + +import java.lang.Exception; + +/** + * @deprecated for internal use + * The Class ListenRoleChangeAddException. + */ +public class ListenRoleChangeAddException extends Exception { + + /** + * Instantiates a new listen role change add exception. + */ + public ListenRoleChangeAddException() { + super(); + } +} diff --git a/opendaylight/clustering/services_implementation/pom.xml b/opendaylight/clustering/services_implementation/pom.xml new file mode 100644 index 0000000000..82a97b666f --- /dev/null +++ b/opendaylight/clustering/services_implementation/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + org.opendaylight.controller + clustering.services-implementation + 0.4.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.slf4j, + !org.jboss.*, + !bsh*, + !net.jcip.*, + javax.transaction, + *, + org.opendaylight.controller.clustering.services, + org.opendaylight.controller.sal.core + + + org.opendaylight.controller.clustering.services_implementation.internal.Activator + + + + + + + + + + * + + + infinispan-core,jgroups,jboss-marshalling-river,jboss-marshalling,jboss-logging,staxmapper;type=!pom;inline=false + + + true + + + + + + + + + org.infinispan + infinispan-core + 5.2.3.Final + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.4.0-SNAPSHOT + + + diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/Activator.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/Activator.java new file mode 100644 index 0000000000..79af2cf398 --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/Activator.java @@ -0,0 +1,149 @@ + +/* + * 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.controller.clustering.services_implementation.internal; + +import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; + +import org.opendaylight.controller.clustering.services.ICacheUpdateAware; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterGlobalServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.clustering.services.ICoordinatorChangeAware; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.felix.dm.Component; + +public class Activator extends ComponentActivatorAbstractBase { + protected static final Logger logger = LoggerFactory + .getLogger(Activator.class); + + /** + * Function called when the activator starts just after some + * initializations are done by the + * ComponentActivatorAbstractBase. + * + */ + public void init() { + } + + /** + * Function called when the activator stops just before the + * cleanup done by ComponentActivatorAbstractBase + * + */ + public void destroy() { + } + + /** + * Function that is used to communicate to dependency manager the + * list of known implementations for services inside a container + * + * + * @return An array containing all the CLASS objects that will be + * instantiated in order to get an fully working implementation + * Object + */ + public Object[] getGlobalImplementations() { + Object[] res = { ClusterManager.class, ClusterGlobalManager.class }; + return res; + } + + /** + * Function that is used to communicate to dependency manager the + * list of known implementations for services inside a container + * + * + * @return An array containing all the CLASS objects that will be + * instantiated in order to get an fully working implementation + * Object + */ + public Object[] getImplementations() { + Object[] res = { ClusterContainerManager.class }; + return res; + } + + /** + * Function that is called when configuration of the dependencies + * is required. + * + * @param c dependency manager Component object, used for + * configuring the dependencies exported and imported + * @param imp Implementation class that is being configured, + * needed as long as the same routine can configure multiple + * implementations + * @param containerName The containerName being configured, this allow + * also optional per-container different behavior if needed, usually + * should not be the case though. + */ + public void configureInstance(Component c, Object imp, String containerName) { + if (imp.equals(ClusterContainerManager.class)) { + c.setInterface(new String[] { IClusterContainerServices.class + .getName() }, null); + + c.add(createServiceDependency().setService(IClusterServices.class) + .setCallbacks("setClusterService", "unsetClusterService") + .setRequired(true)); + + // CacheUpdate services will be none or many so the + // dependency is optional + c.add(createContainerServiceDependency(containerName).setService( + ICacheUpdateAware.class).setCallbacks( + "setCacheUpdateAware", "unsetCacheUpdateAware") + .setRequired(false)); + + // Coordinator change event can be one or many so + // dependency is optional + c.add(createContainerServiceDependency(containerName).setService( + ICoordinatorChangeAware.class).setCallbacks( + "setCoordinatorChangeAware", "unsetCoordinatorChangeAware") + .setRequired(false)); + } + } + + /** + * Function that is called when configuration of the dependencies + * is required. + * + * @param c dependency manager Component object, used for + * configuring the dependencies exported and imported + * @param imp Implementation class that is being configured, + * needed as long as the same routine can configure multiple + * implementations + */ + public void configureGlobalInstance(Component c, Object imp) { + if (imp.equals(ClusterManager.class)) { + // export the service for Apps and Plugins + c.setInterface(new String[] { IClusterServices.class.getName() }, + null); + } + + if (imp.equals(ClusterGlobalManager.class)) { + c.setInterface(new String[] { IClusterGlobalServices.class + .getName() }, null); + + c.add(createServiceDependency().setService(IClusterServices.class) + .setCallbacks("setClusterService", "unsetClusterService") + .setRequired(true)); + + // CacheUpdate services will be none or many so the + // dependency is optional + c.add(createServiceDependency().setService(ICacheUpdateAware.class) + .setCallbacks("setCacheUpdateAware", + "unsetCacheUpdateAware").setRequired(false)); + + // Coordinator change event can be one or many so + // dependency is optional + c.add(createServiceDependency().setService( + ICoordinatorChangeAware.class).setCallbacks( + "setCoordinatorChangeAware", "unsetCoordinatorChangeAware") + .setRequired(false)); + } + } +} diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/CacheListenerContainer.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/CacheListenerContainer.java new file mode 100644 index 0000000000..c3c0621e8c --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/CacheListenerContainer.java @@ -0,0 +1,73 @@ + +/* + * 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.controller.clustering.services_implementation.internal; + +import org.infinispan.notifications.Listener; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved; +import org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent; +import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent; +import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent; +import org.opendaylight.controller.clustering.services.IGetUpdates; + +@Listener +public class CacheListenerContainer { + private IGetUpdates toBeUpdated; + private String containerName; + private String cacheName; + + public CacheListenerContainer(IGetUpdates i, String containerName, + String cacheName) { + this.toBeUpdated = i; + this.containerName = containerName; + this.cacheName = cacheName; + } + + public IGetUpdates whichListener() { + return this.toBeUpdated; + } + + @CacheEntryCreated + public void observeCreate(CacheEntryCreatedEvent event) { + if (event.isPre()) { + return; + } + + if (this.toBeUpdated != null) { + this.toBeUpdated.entryCreated(event.getKey(), this.containerName, + this.cacheName, event.isOriginLocal()); + } + } + + @CacheEntryModified + public void observeModify(CacheEntryModifiedEvent event) { + if (event.isPre()) { + return; + } + + if (this.toBeUpdated != null) { + this.toBeUpdated.entryUpdated(event.getKey(), event.getValue(), + this.containerName, this.cacheName, event.isOriginLocal()); + } + } + + @CacheEntryRemoved + public void observeRemove(CacheEntryRemovedEvent event) { + if (event.isPre()) { + return; + } + + if (this.toBeUpdated != null) { + this.toBeUpdated.entryDeleted(event.getKey(), this.containerName, + this.cacheName, event.isOriginLocal()); + } + } +} diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterContainerManager.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterContainerManager.java new file mode 100644 index 0000000000..9496c33191 --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterContainerManager.java @@ -0,0 +1,16 @@ + +/* + * 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.controller.clustering.services_implementation.internal; + +import org.opendaylight.controller.clustering.services.IClusterContainerServices; + +public class ClusterContainerManager extends ClusterManagerCommon implements + IClusterContainerServices { +} diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterGlobalManager.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterGlobalManager.java new file mode 100644 index 0000000000..8211846dd6 --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterGlobalManager.java @@ -0,0 +1,16 @@ + +/* + * 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.controller.clustering.services_implementation.internal; + +import org.opendaylight.controller.clustering.services.IClusterGlobalServices; + +public class ClusterGlobalManager extends ClusterManagerCommon implements + IClusterGlobalServices { +} diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java new file mode 100644 index 0000000000..d3cd23e350 --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManager.java @@ -0,0 +1,672 @@ + +/* + * 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.controller.clustering.services_implementation.internal; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentMap; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; + +import org.infinispan.Cache; +import org.infinispan.configuration.cache.Configuration; +import org.infinispan.manager.DefaultCacheManager; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.notifications.Listener; +import org.infinispan.notifications.cachemanagerlistener.annotation.ViewChanged; +import org.infinispan.notifications.cachemanagerlistener.event.ViewChangedEvent; +import org.infinispan.remoting.transport.Address; +import org.infinispan.remoting.transport.Transport; +import org.infinispan.remoting.transport.jgroups.JGroupsAddress; +import org.infinispan.remoting.transport.jgroups.JGroupsTransport; +import org.jgroups.Channel; +import org.jgroups.Event; +import org.jgroups.stack.GossipRouter; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.CacheListenerAddException; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.clustering.services.IGetUpdates; +import org.opendaylight.controller.clustering.services.IListenRoleChange; +import org.opendaylight.controller.clustering.services.ListenRoleChangeAddException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClusterManager implements IClusterServices { + protected static final Logger logger = LoggerFactory + .getLogger(ClusterManager.class); + private DefaultCacheManager cm; + GossipRouter gossiper; + private HashSet roleChangeListeners; + private ViewChangedListener cacheManagerListener; + + private static String loopbackAddress = "127.0.0.1"; + + /** + * Start a JGroups GossipRouter if we are a supernode. The + * GosispRouter is nothing more than a simple + * rendevouz-pointer. All the nodes that wants to join the cluster + * will come to any of the rendevouz point and they introduce the + * nodes to all the others. Once the meet and greet phase if over, + * the nodes will open a full-mesh with the remaining n-1 nodes, + * so even if the GossipRouter goes down nothing is lost. + * NOTE: This function has the side effect to set some of the + * JGROUPS configurations, this because in this function already + * we try to retrieve some of the network capabilities of the + * device and so it's better not to do that again + * + * + * @return GossipRouter + */ + private GossipRouter startGossiper() { + boolean amIGossipRouter = false; + Integer gossipRouterPortDefault = 12001; + Integer gossipRouterPort = gossipRouterPortDefault; + InetAddress gossipRouterAddress = null; + String supernodes_list = System.getProperty("supernodes", + loopbackAddress); + StringBuffer sanitized_supernodes_list = new StringBuffer(); + List myAddresses = new ArrayList(); + + StringTokenizer supernodes = new StringTokenizer(supernodes_list, ":"); + if (supernodes.hasMoreTokens()) { + // Populate the list of my addresses + try { + Enumeration e = NetworkInterface.getNetworkInterfaces(); + while (e.hasMoreElements()) { + NetworkInterface n = (NetworkInterface) e.nextElement(); + Enumeration ee = n.getInetAddresses(); + while (ee.hasMoreElements()) { + InetAddress i = (InetAddress) ee.nextElement(); + myAddresses.add(i); + } + } + } catch (SocketException se) { + logger.error("Cannot get the list of network interfaces"); + return null; + } + } + while (supernodes.hasMoreTokens()) { + String curr_supernode = supernodes.nextToken(); + logger.debug("Examining supernode " + curr_supernode); + StringTokenizer host_port = new StringTokenizer(curr_supernode, + "[]"); + String host; + String port; + Integer port_num = gossipRouterPortDefault; + if (host_port.countTokens() > 2) { + logger.error("Error parsing supernode " + curr_supernode + + " proceed to the next one"); + continue; + } + host = host_port.nextToken(); + InetAddress hostAddr; + try { + hostAddr = InetAddress.getByName(host); + } catch (UnknownHostException ue) { + logger.error("Host not known"); + continue; + } + if (host_port.hasMoreTokens()) { + port = host_port.nextToken(); + try { + port_num = Integer.valueOf(port); + } catch (NumberFormatException ne) { + logger + .error("Supplied supernode gossiepr port is not recognized, using standard gossipport"); + port_num = gossipRouterPortDefault; + } + if ((port_num > 65535) || (port_num < 0)) { + logger + .error("Supplied supernode gossip port is outside a valid TCP port range"); + port_num = gossipRouterPortDefault; + } + } + if (!amIGossipRouter) { + if (host != null) { + for (InetAddress myAddr : myAddresses) { + if (myAddr.equals(hostAddr)) { + amIGossipRouter = true; + gossipRouterAddress = hostAddr; + gossipRouterPort = port_num; + break; + } + } + } + } + if (!sanitized_supernodes_list.toString().equals("")) { + sanitized_supernodes_list.append(","); + } + sanitized_supernodes_list.append(hostAddr.getHostAddress() + "[" + + port_num + "]"); + } + + if (amIGossipRouter) { + // Set the Jgroups binding interface to the one we got + // from the supernodes attribute + if (gossipRouterAddress != null) { + System.setProperty("jgroups.tcp.address", gossipRouterAddress + .getHostAddress()); + } + } else { + // Set the Jgroup binding interface to the one we are well + // known outside or else to the first with non-local + // scope. + try { + String myBind = InetAddress.getLocalHost().getHostAddress(); + if (myBind == null + || InetAddress.getLocalHost().isLoopbackAddress()) { + for (InetAddress myAddr : myAddresses) { + if (myAddr.isLoopbackAddress() + || myAddr.isLinkLocalAddress()) { + logger.debug("Skipping local address " + + myAddr.getHostAddress()); + continue; + } else { + // First non-local address + myBind = myAddr.getHostAddress(); + logger.debug("First non-local address " + myBind); + break; + } + } + } + String jgroupAddress = System + .getProperty("jgroups.tcp.address"); + if (jgroupAddress == null) { + if (myBind != null) { + logger.debug("Set bind address to be " + myBind); + System.setProperty("jgroups.tcp.address", myBind); + } else { + logger + .debug("Set bind address to be LOCALHOST=127.0.0.1"); + System.setProperty("jgroups.tcp.address", "127.0.0.1"); + } + } else { + logger.debug("jgroup.tcp.address already set to be " + + jgroupAddress); + } + } catch (UnknownHostException uhe) { + logger + .error("Met UnknownHostException while trying to get binding address for jgroups"); + } + } + + // The supernodes list constitute also the tcpgossip initial + // host list + System.setProperty("jgroups.tcpgossip.initial_hosts", + sanitized_supernodes_list.toString()); + logger.debug("jgroups.tcp.address set to " + + System.getProperty("jgroups.tcp.address")); + logger.debug("jgroups.tcpgossip.initial_hosts set to " + + System.getProperty("jgroups.tcpgossip.initial_hosts")); + GossipRouter res = null; + if (amIGossipRouter) { + logger.info("I'm a GossipRouter will listen on port " + + gossipRouterPort); + res = new GossipRouter(gossipRouterPort); + } + return res; + } + + public void start() { + this.gossiper = startGossiper(); + if (this.gossiper != null) { + logger.debug("Trying to start Gossiper"); + try { + this.gossiper.start(); + logger.info("Started GossipRouter"); + } catch (Exception e) { + logger.error("GossipRouter didn't start exception " + e + + " met"); + StringWriter sw = new StringWriter(); + logger.error("Stack Trace that raised the exception"); + e.printStackTrace(new PrintWriter(sw)); + logger.error(sw.toString()); + } + } + logger.info("Starting the ClusterManager"); + try { + //FIXME keeps throwing FileNotFoundException + this.cm = new DefaultCacheManager("/config/infinispan-config.xml"); + logger.debug("Allocated ClusterManager"); + if (this.cm != null) { + this.cm.start(); + this.cm.startCache(); + logger.debug("Started the ClusterManager"); + } + } catch (Exception ioe) { + StringWriter sw = new StringWriter(); + logger.error("Cannot configure infinispan .. bailing out "); + logger.error("Stack Trace that raised th exception"); + ioe.printStackTrace(new PrintWriter(sw)); + logger.error(sw.toString()); + this.cm = null; + this.stop(); + } + logger.debug("Cache Manager has value " + this.cm); + } + + public void stop() { + logger.info("Stopping the ClusterManager"); + if (this.cm != null) { + logger.info("Found a valid ClusterManager, now let it be stopped"); + this.cm.stop(); + this.cm = null; + } + if (this.gossiper != null) { + this.gossiper.stop(); + this.gossiper = null; + } + } + + @Override + public ConcurrentMap createCache(String containerName, + String cacheName, Set cMode) throws CacheExistException, + CacheConfigException { + EmbeddedCacheManager manager = this.cm; + Cache c; + String realCacheName = "{" + containerName + "}_{" + cacheName + "}"; + if (manager == null) { + return null; + } + + if (manager.cacheExists(realCacheName)) { + throw new CacheExistException(); + } + + // Sanity check to avoid contrasting parameters + if (cMode.containsAll(EnumSet.of( + IClusterServices.cacheMode.NON_TRANSACTIONAL, + IClusterServices.cacheMode.TRANSACTIONAL))) { + throw new CacheConfigException(); + } + + if (cMode.contains(IClusterServices.cacheMode.NON_TRANSACTIONAL)) { + c = manager.getCache(realCacheName); + return c; + } else if (cMode.contains(IClusterServices.cacheMode.TRANSACTIONAL)) { + Configuration rc = manager + .getCacheConfiguration("transactional-type"); + manager.defineConfiguration(realCacheName, rc); + c = manager.getCache(realCacheName); + return c; + } + return null; + } + + @Override + public ConcurrentMap getCache(String containerName, String cacheName) { + EmbeddedCacheManager manager = this.cm; + Cache c; + String realCacheName = "{" + containerName + "}_{" + cacheName + "}"; + if (manager == null) { + return null; + } + + if (manager.cacheExists(realCacheName)) { + c = manager.getCache(realCacheName); + return c; + } + return null; + } + + @Override + public void destroyCache(String containerName, String cacheName) { + EmbeddedCacheManager manager = this.cm; + String realCacheName = "{" + containerName + "}_{" + cacheName + "}"; + if (manager == null) { + return; + } + if (manager.cacheExists(realCacheName)) { + manager.removeCache(realCacheName); + } + } + + @Override + public boolean existCache(String containerName, String cacheName) { + EmbeddedCacheManager manager = this.cm; + String realCacheName = "{" + containerName + "}_{" + cacheName + "}"; + if (manager == null) { + return false; + } + return manager.cacheExists(realCacheName); + } + + @Override + public Set getCacheList(String containerName) { + Set perContainerCaches = new HashSet(); + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + return null; + } + for (String cacheName : manager.getCacheNames()) { + if (cacheName.startsWith("{" + containerName + "}_")) { + String[] res = cacheName.split("[{}]"); + if (res.length >= 4 && res[1].equals(containerName) + && res[2].equals("_")) { + perContainerCaches.add(res[3]); + } + } + } + + return (perContainerCaches); + } + + @Override + public Properties getCacheProperties(String containerName, String cacheName) { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + return null; + } + String realCacheName = "{" + containerName + "}_{" + cacheName + "}"; + if (!manager.cacheExists(realCacheName)) { + return null; + } + Configuration conf = manager.getCache(realCacheName).getAdvancedCache() + .getCacheConfiguration(); + Properties p = new Properties(); + p.setProperty(IClusterServices.cacheProps.TRANSACTION_PROP.toString(), + conf.transaction().toString()); + p.setProperty(IClusterServices.cacheProps.CLUSTERING_PROP.toString(), + conf.clustering().toString()); + p.setProperty(IClusterServices.cacheProps.LOCKING_PROP.toString(), conf + .locking().toString()); + return p; + } + + @Override + public void addListener(String containerName, String cacheName, + IGetUpdates u) throws CacheListenerAddException { + EmbeddedCacheManager manager = this.cm; + Cache c; + String realCacheName = "{" + containerName + "}_{" + cacheName + "}"; + if (manager == null) { + return; + } + + if (!manager.cacheExists(realCacheName)) { + throw new CacheListenerAddException(); + } + c = manager.getCache(realCacheName); + CacheListenerContainer cl = new CacheListenerContainer(u, + containerName, cacheName); + if (cl == null) { + throw new CacheListenerAddException(); + } + c.addListener(cl); + } + + @Override + public Set> getListeners(String containerName, + String cacheName) { + EmbeddedCacheManager manager = this.cm; + Cache c; + String realCacheName = "{" + containerName + "}_{" + cacheName + "}"; + if (manager == null) { + return null; + } + + if (!manager.cacheExists(realCacheName)) { + return null; + } + c = manager.getCache(realCacheName); + + Set> res = new HashSet(); + Set listeners = c.getListeners(); + for (Object listener : listeners) { + if (listener instanceof CacheListenerContainer) { + CacheListenerContainer cl = (CacheListenerContainer) listener; + res.add(cl.whichListener()); + } + } + + return res; + } + + @Override + public void removeListener(String containerName, String cacheName, + IGetUpdates u) { + EmbeddedCacheManager manager = this.cm; + Cache c; + String realCacheName = "{" + containerName + "}_{" + cacheName + "}"; + if (manager == null) { + return; + } + + if (!manager.cacheExists(realCacheName)) { + return; + } + c = manager.getCache(realCacheName); + + Set listeners = c.getListeners(); + for (Object listener : listeners) { + if (listener instanceof CacheListenerContainer) { + CacheListenerContainer cl = (CacheListenerContainer) listener; + if (cl.whichListener() == u) { + c.removeListener(listener); + return; + } + } + } + } + + @Override + public void tbegin() throws NotSupportedException, SystemException { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + throw new IllegalStateException(); + } + TransactionManager tm = manager.getCache("transactional-type") + .getAdvancedCache().getTransactionManager(); + if (tm == null) { + throw new IllegalStateException(); + } + tm.begin(); + } + + @Override + public void tcommit() throws RollbackException, HeuristicMixedException, + HeuristicRollbackException, java.lang.SecurityException, + java.lang.IllegalStateException, SystemException { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + throw new IllegalStateException(); + } + TransactionManager tm = manager.getCache("transactional-type") + .getAdvancedCache().getTransactionManager(); + if (tm == null) { + throw new IllegalStateException(); + } + tm.commit(); + } + + @Override + public void trollback() throws java.lang.IllegalStateException, + java.lang.SecurityException, SystemException { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + throw new IllegalStateException(); + } + TransactionManager tm = manager.getCache("transactional-type") + .getAdvancedCache().getTransactionManager(); + if (tm == null) { + throw new IllegalStateException(); + } + tm.rollback(); + } + + @Override + public Transaction tgetTransaction() throws SystemException { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + throw new IllegalStateException(); + } + TransactionManager tm = manager.getCache("transactional-type") + .getAdvancedCache().getTransactionManager(); + if (tm == null) { + return null; + } + return tm.getTransaction(); + } + + @Override + public boolean amIStandby() { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + // In case we cannot fetch the information, lets assume we + // are standby, so to have less responsability. + return true; + } + return (!manager.isCoordinator()); + } + + private InetAddress addressToInetAddress(Address a) { + EmbeddedCacheManager manager = this.cm; + if ((manager == null) || (a == null)) { + // In case we cannot fetch the information, lets assume we + // are standby, so to have less responsability. + return null; + } + Transport t = manager.getTransport(); + if (t instanceof JGroupsTransport) { + JGroupsTransport jt = (JGroupsTransport) t; + Channel c = jt.getChannel(); + if (a instanceof JGroupsAddress) { + JGroupsAddress ja = (JGroupsAddress) a; + org.jgroups.Address phys = (org.jgroups.Address) c + .down(new Event(Event.GET_PHYSICAL_ADDRESS, ja + .getJGroupsAddress())); + if (phys instanceof org.jgroups.stack.IpAddress) { + InetAddress bindAddress = ((org.jgroups.stack.IpAddress) phys) + .getIpAddress(); + return bindAddress; + } + } + } + return null; + } + + public List getClusteredControllers() { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + return null; + } + List
controllers = manager.getMembers(); + if ((controllers == null) || controllers.size() == 0) + return null; + + List clusteredControllers = new ArrayList(); + for (Address a : controllers) { + InetAddress inetAddress = addressToInetAddress(a); + if (inetAddress != null + && !inetAddress.getHostAddress().equals(loopbackAddress)) + clusteredControllers.add(inetAddress); + } + return clusteredControllers; + } + + public InetAddress getMyAddress() { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + return null; + } + return addressToInetAddress(manager.getAddress()); + } + + @Override + public InetAddress getActiveAddress() { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + // In case we cannot fetch the information, lets assume we + // are standby, so to have less responsability. + return null; + } + + return addressToInetAddress(manager.getCoordinator()); + } + + @Override + public void listenRoleChange(IListenRoleChange i) + throws ListenRoleChangeAddException { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + // In case we cannot fetch the information, lets assume we + // are standby, so to have less responsability. + throw new ListenRoleChangeAddException(); + } + + if (this.roleChangeListeners == null) { + this.roleChangeListeners = new HashSet(); + this.cacheManagerListener = new ViewChangedListener( + this.roleChangeListeners); + manager.addListener(this.cacheManagerListener); + } + + if (this.roleChangeListeners != null) { + this.roleChangeListeners.add(i); + } + } + + @Override + public void unlistenRoleChange(IListenRoleChange i) { + EmbeddedCacheManager manager = this.cm; + if (manager == null) { + // In case we cannot fetch the information, lets assume we + // are standby, so to have less responsability. + return; + } + + if (this.roleChangeListeners != null) { + this.roleChangeListeners.remove(i); + } + + if ((this.roleChangeListeners != null && this.roleChangeListeners + .isEmpty()) + && (this.cacheManagerListener != null)) { + manager.removeListener(this.cacheManagerListener); + this.cacheManagerListener = null; + this.roleChangeListeners = null; + } + } + + @Listener + public class ViewChangedListener { + Set roleListeners; + + public ViewChangedListener(Set s) { + this.roleListeners = s; + } + + @ViewChanged + public void viewChanged(ViewChangedEvent e) { + for (IListenRoleChange i : this.roleListeners) { + i.newActiveAvailable(); + } + } + } +} diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCommon.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCommon.java new file mode 100644 index 0000000000..2afbabe87f --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCommon.java @@ -0,0 +1,282 @@ + +/* + * 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.controller.clustering.services_implementation.internal; + +import java.net.InetAddress; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; + +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.CacheListenerAddException; +import org.opendaylight.controller.clustering.services.ICacheUpdateAware; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.clustering.services.IClusterServicesCommon; +import org.opendaylight.controller.clustering.services.ICoordinatorChangeAware; +import org.opendaylight.controller.clustering.services.IListenRoleChange; +import org.opendaylight.controller.clustering.services.ListenRoleChangeAddException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Dictionary; +import java.util.Collections; +import java.util.HashSet; +import org.apache.felix.dm.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +abstract public class ClusterManagerCommon implements IClusterServicesCommon { + protected String containerName = null; + private IClusterServices clusterService = null; + protected static final Logger logger = LoggerFactory + .getLogger(ClusterManagerCommon.class); + private Set cacheUpdateAware = Collections + .synchronizedSet(new HashSet()); + private Set coordinatorChangeAware = Collections + .synchronizedSet(new HashSet()); + private ListenCoordinatorChange coordinatorChangeListener = null; + + /** + * Class needed to listen to the role changes from the cluster + * manager and to pass it along to the other components that + * export the interface ICoordinatorChangeAware + */ + class ListenCoordinatorChange implements IListenRoleChange { + public void newActiveAvailable() { + if (coordinatorChangeAware != null) { + // Make sure to look the set while walking it + synchronized (coordinatorChangeAware) { + for (ICoordinatorChangeAware s : coordinatorChangeAware) { + // Now walk every instance and signal that the + // coordinator has changed + s.coordinatorChanged(); + } + } + } + } + } + + void setCoordinatorChangeAware(ICoordinatorChangeAware s) { + if (this.coordinatorChangeAware != null) { + this.coordinatorChangeAware.add(s); + } + } + + void unsetCoordinatorChangeAware(ICoordinatorChangeAware s) { + if (this.coordinatorChangeAware != null) { + this.coordinatorChangeAware.remove(s); + } + } + + void setCacheUpdateAware(ICacheUpdateAware s) { + if (this.cacheUpdateAware != null) { + this.cacheUpdateAware.add(s); + } + } + + void unsetCacheUpdateAware(ICacheUpdateAware s) { + if (this.cacheUpdateAware != null) { + this.cacheUpdateAware.remove(s); + } + } + + public void setClusterService(IClusterServices s) { + this.clusterService = s; + } + + public void unsetClusterServices(IClusterServices s) { + if (this.clusterService == s) { + this.clusterService = null; + } + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName:" + this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + if (this.clusterService != null) { + this.coordinatorChangeListener = new ListenCoordinatorChange(); + try { + this.clusterService + .listenRoleChange(this.coordinatorChangeListener); + logger.debug("Coordinator change handler registered"); + } catch (ListenRoleChangeAddException ex) { + logger.error("Could not register coordinator change"); + } + } + } + + /** + * Function called by the dependency manager when any of the required + * dependencies are going away + * + */ + void destroy() { + if (this.clusterService != null + && this.coordinatorChangeListener != null) { + this.clusterService + .unlistenRoleChange(this.coordinatorChangeListener); + this.coordinatorChangeListener = null; + logger.debug("Coordinator change handler UNregistered"); + } + } + + @Override + public ConcurrentMap createCache(String cacheName, + Set cMode) throws CacheExistException, + CacheConfigException { + if (this.clusterService != null) { + return this.clusterService.createCache(this.containerName, + cacheName, cMode); + } else { + return null; + } + } + + @Override + public ConcurrentMap getCache(String cacheName) { + if (this.clusterService != null) { + return this.clusterService.getCache(this.containerName, cacheName); + } else { + return null; + } + } + + @Override + public void destroyCache(String cacheName) { + if (this.clusterService != null) { + this.clusterService.destroyCache(this.containerName, cacheName); + } + } + + @Override + public boolean existCache(String cacheName) { + if (this.clusterService != null) { + return this.clusterService + .existCache(this.containerName, cacheName); + } else { + return false; + } + } + + @Override + public Set getCacheList() { + if (this.clusterService != null) { + return this.clusterService.getCacheList(this.containerName); + } else { + return null; + } + } + + @Override + public Properties getCacheProperties(String cacheName) { + if (this.clusterService != null) { + return this.clusterService.getCacheProperties(this.containerName, + cacheName); + } else { + return null; + } + } + + @Override + public void tbegin() throws NotSupportedException, SystemException { + if (this.clusterService != null) { + this.clusterService.tbegin(); + } else { + throw new IllegalStateException(); + } + } + + @Override + public void tcommit() throws RollbackException, HeuristicMixedException, + HeuristicRollbackException, java.lang.SecurityException, + java.lang.IllegalStateException, SystemException { + if (this.clusterService != null) { + this.clusterService.tcommit(); + } else { + throw new IllegalStateException(); + } + } + + @Override + public void trollback() throws java.lang.IllegalStateException, + java.lang.SecurityException, SystemException { + if (this.clusterService != null) { + this.clusterService.trollback(); + } else { + throw new IllegalStateException(); + } + } + + @Override + public Transaction tgetTransaction() throws SystemException { + if (this.clusterService != null) { + return this.clusterService.tgetTransaction(); + } else { + return null; + } + } + + @Override + public List getClusteredControllers() { + if (this.clusterService != null) { + return this.clusterService.getClusteredControllers(); + } else { + return null; + } + } + + @Override + public InetAddress getMyAddress() { + if (this.clusterService != null) { + return this.clusterService.getMyAddress(); + } else { + return null; + } + } + + @Override + public InetAddress getCoordinatorAddress() { + if (this.clusterService != null) { + return this.clusterService.getActiveAddress(); + } else { + return null; + } + } + + @Override + public boolean amICoordinator() { + if (this.clusterService != null) { + return (!this.clusterService.amIStandby()); + } else { + return false; + } + } +} diff --git a/opendaylight/clustering/services_implementation/src/main/resources/OSGI-INF/component-cachemanager.xml b/opendaylight/clustering/services_implementation/src/main/resources/OSGI-INF/component-cachemanager.xml new file mode 100644 index 0000000000..f3baf79e8a --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/resources/OSGI-INF/component-cachemanager.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml b/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml new file mode 100644 index 0000000000..96eff96919 --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/clustering/services_implementation/src/main/resources/config/jgroups.xml b/opendaylight/clustering/services_implementation/src/main/resources/config/jgroups.xml new file mode 100644 index 0000000000..b1dc0334e5 --- /dev/null +++ b/opendaylight/clustering/services_implementation/src/main/resources/config/jgroups.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/clustering/stub/pom.xml b/opendaylight/clustering/stub/pom.xml new file mode 100644 index 0000000000..2670c723f4 --- /dev/null +++ b/opendaylight/clustering/stub/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + org.opendaylight.controller + clustering.stub + 0.4.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + javax.transaction, + org.apache.felix.dm, + org.slf4j, + org.opendaylight.controller.clustering.services, + org.opendaylight.controller.sal.core + + + org.opendaylight.controller.clustering.stub.internal.Activator + + + + + + + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.4.0-SNAPSHOT + + + diff --git a/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/Activator.java b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/Activator.java new file mode 100644 index 0000000000..e73155a3e8 --- /dev/null +++ b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/Activator.java @@ -0,0 +1,108 @@ + +/* + * 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.controller.clustering.stub.internal; + +import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; + +import org.opendaylight.controller.clustering.services.ICacheUpdateAware; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterGlobalServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.clustering.services.ICoordinatorChangeAware; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.felix.dm.Component; + +public class Activator extends ComponentActivatorAbstractBase { + protected static final Logger logger = LoggerFactory + .getLogger(Activator.class); + + /** + * Function called when the activator starts just after some + * initializations are done by the + * ComponentActivatorAbstractBase. + * + */ + public void init() { + } + + /** + * Function called when the activator stops just before the + * cleanup done by ComponentActivatorAbstractBase + * + */ + public void destroy() { + } + + /** + * Function that is used to communicate to dependency manager the + * list of known implementations for services inside a container + * + * + * @return An array containing all the CLASS objects that will be + * instantiated in order to get an fully working implementation + * Object + */ + public Object[] getGlobalImplementations() { + Object[] res = { ClusterGlobalManager.class }; + return res; + } + + /** + * Function that is used to communicate to dependency manager the + * list of known implementations for services inside a container + * + * + * @return An array containing all the CLASS objects that will be + * instantiated in order to get an fully working implementation + * Object + */ + public Object[] getImplementations() { + Object[] res = { ClusterContainerManager.class }; + return res; + } + + /** + * Function that is called when configuration of the dependencies + * is required. + * + * @param c dependency manager Component object, used for + * configuring the dependencies exported and imported + * @param imp Implementation class that is being configured, + * needed as long as the same routine can configure multiple + * implementations + * @param containerName The containerName being configured, this allow + * also optional per-container different behavior if needed, usually + * should not be the case though. + */ + public void configureInstance(Component c, Object imp, String containerName) { + if (imp.equals(ClusterContainerManager.class)) { + c.setInterface(new String[] { IClusterContainerServices.class + .getName() }, null); + } + } + + /** + * Function that is called when configuration of the dependencies + * is required. + * + * @param c dependency manager Component object, used for + * configuring the dependencies exported and imported + * @param imp Implementation class that is being configured, + * needed as long as the same routine can configure multiple + * implementations + */ + public void configureGlobalInstance(Component c, Object imp) { + if (imp.equals(ClusterGlobalManager.class)) { + c.setInterface(new String[] { IClusterGlobalServices.class + .getName() }, null); + } + } +} diff --git a/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterContainerManager.java b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterContainerManager.java new file mode 100644 index 0000000000..627db22a0a --- /dev/null +++ b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterContainerManager.java @@ -0,0 +1,21 @@ + +/* + * 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.controller.clustering.stub.internal; + +import java.net.UnknownHostException; + +import org.opendaylight.controller.clustering.services.IClusterContainerServices; + +public class ClusterContainerManager extends ClusterManagerCommon implements + IClusterContainerServices { + public ClusterContainerManager() throws UnknownHostException { + super(); + } +} diff --git a/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterGlobalManager.java b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterGlobalManager.java new file mode 100644 index 0000000000..f9f9be8db2 --- /dev/null +++ b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterGlobalManager.java @@ -0,0 +1,21 @@ + +/* + * 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.controller.clustering.stub.internal; + +import java.net.UnknownHostException; + +import org.opendaylight.controller.clustering.services.IClusterGlobalServices; + +public class ClusterGlobalManager extends ClusterManagerCommon implements + IClusterGlobalServices { + public ClusterGlobalManager() throws UnknownHostException { + super(); + } +} diff --git a/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterManagerCommon.java b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterManagerCommon.java new file mode 100644 index 0000000000..13d05bb7be --- /dev/null +++ b/opendaylight/clustering/stub/src/main/java/org/opendaylight/controller/clustering/stub/internal/ClusterManagerCommon.java @@ -0,0 +1,164 @@ + +/* + * 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.controller.clustering.stub.internal; + +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; +import java.net.UnknownHostException; +import java.net.InetAddress; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; + +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.CacheListenerAddException; +import org.opendaylight.controller.clustering.services.ICacheUpdateAware; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.clustering.services.IClusterServicesCommon; +import org.opendaylight.controller.clustering.services.ICoordinatorChangeAware; +import org.opendaylight.controller.clustering.services.IListenRoleChange; +import org.opendaylight.controller.clustering.services.ListenRoleChangeAddException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Dictionary; +import java.util.Collections; +import java.util.HashSet; +import org.apache.felix.dm.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +abstract public class ClusterManagerCommon implements IClusterServicesCommon { + protected String containerName = ""; + protected static final Logger logger = LoggerFactory + .getLogger(ClusterManagerCommon.class); + private InetAddress loopbackAddress; + private ConcurrentMap> caches = new ConcurrentHashMap>(); + + protected ClusterManagerCommon() throws UnknownHostException { + loopbackAddress = InetAddress.getByName("127.0.0.1"); + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName:" + this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + } + + /** + * Function called by the dependency manager when any of the required + * dependencies are going away + * + */ + void destroy() { + // Clear the caches, will restart on the new life + this.caches.clear(); + } + + @Override + public ConcurrentMap createCache(String cacheName, + Set cMode) throws CacheExistException, + CacheConfigException { + ConcurrentMap res = this.caches.get(cacheName); + if (res == null) { + res = new ConcurrentHashMap(); + this.caches.put(cacheName, res); + return res; + } + throw new CacheExistException(); + } + + @Override + public ConcurrentMap getCache(String cacheName) { + return this.caches.get(cacheName); + } + + @Override + public void destroyCache(String cacheName) { + this.caches.remove(cacheName); + } + + @Override + public boolean existCache(String cacheName) { + return (this.caches.get(cacheName) != null); + } + + @Override + public Set getCacheList() { + return this.caches.keySet(); + } + + @Override + public Properties getCacheProperties(String cacheName) { + return null; + } + + @Override + public void tbegin() throws NotSupportedException, SystemException { + } + + @Override + public void tcommit() throws RollbackException, HeuristicMixedException, + HeuristicRollbackException, java.lang.SecurityException, + java.lang.IllegalStateException, SystemException { + } + + @Override + public void trollback() throws java.lang.IllegalStateException, + java.lang.SecurityException, SystemException { + } + + @Override + public Transaction tgetTransaction() throws SystemException { + return null; + } + + @Override + public List getClusteredControllers() { + List res = new ArrayList(); + res.add(loopbackAddress); + return res; + } + + @Override + public InetAddress getMyAddress() { + return loopbackAddress; + } + + @Override + public InetAddress getCoordinatorAddress() { + return loopbackAddress; + } + + @Override + public boolean amICoordinator() { + return true; + } +} diff --git a/opendaylight/clustering/stub/src/test/java/org/opendaylight/controller/clustering/stub/internal/TestClusteringStub.java b/opendaylight/clustering/stub/src/test/java/org/opendaylight/controller/clustering/stub/internal/TestClusteringStub.java new file mode 100644 index 0000000000..af1daae5bc --- /dev/null +++ b/opendaylight/clustering/stub/src/test/java/org/opendaylight/controller/clustering/stub/internal/TestClusteringStub.java @@ -0,0 +1,202 @@ + +/* + * 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 + */ + +/** + * @file TestClusteringStub.java + * + * @brief Unit tests for the stub implementation of clustering, + * needed only to run the integration tests + * + * Unit tests for the stub implementation of clustering, + * needed only to run the integration tests + */ +package org.opendaylight.controller.clustering.stub.internal; + +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +import java.net.UnknownHostException; +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterGlobalServices; +import org.opendaylight.controller.clustering.stub.internal.ClusterGlobalManager; + +public class TestClusteringStub { + @Test + public void testStub1() { + IClusterGlobalServices c = null; + ClusterGlobalManager cm = null; + try { + cm = new ClusterGlobalManager(); + c = (IClusterGlobalServices) cm; + } catch (UnknownHostException un) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } + + // Make sure the stub cluster manager is allocated + Assert.assertTrue(cm != null); + Assert.assertTrue(c != null); + + // ======================================== + // Now start testing the several aspects of it. + // ======================================== + + // Allocate few caches + ConcurrentMap c1 = null; + ConcurrentMap c2 = null; + ConcurrentMap c3 = null; + try { + c1 = (ConcurrentMap) c.createCache("c1", null); + } catch (CacheExistException cee) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } catch (CacheConfigException cce) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } + + // Put some data to it + c1.put("FOO", 1); + c1.put("BAZ", 2); + c1.put("BAR", 3); + + try { + c1 = (ConcurrentMap) c.createCache("c1", null); + } catch (CacheExistException cee) { + // This exception should be raised because the cache + // already exists + Assert.assertTrue(true); + } catch (CacheConfigException cce) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } + + // Make sure this cache is retrieved + c1 = (ConcurrentMap) c.getCache("c1"); + Assert.assertTrue(c1 != null); + + // Now make sure the data exists + Integer res = null; + res = c1.get("FOO"); + Assert.assertTrue(res != null); + res = c1.get("BAR"); + Assert.assertTrue(res != null); + res = c1.get("BAZ"); + Assert.assertTrue(res != null); + + // Now create yet another two caches + try { + c2 = (ConcurrentMap) c.createCache("c2", null); + c3 = (ConcurrentMap) c.createCache("c3", null); + } catch (CacheExistException cee) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } catch (CacheConfigException cce) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } + + // Make sure the caches exist + Assert.assertTrue(c2 != null); + Assert.assertTrue(c3 != null); + + // Put some fake data + c2.put("FOO", 11); + c2.put("BAZ", 22); + c2.put("BAR", 33); + + c3.put("FOOBAR", 110); + + // Test for cache existance + Assert.assertTrue(c.existCache("c1")); + Assert.assertTrue(c.existCache("c2")); + Assert.assertTrue(c.existCache("c3")); + + // Get the Cache List + Set caches = c.getCacheList(); + Assert.assertTrue(caches != null); + + // Check if the cachelist is correct + System.out.println("cache size:" + caches.size()); + Assert.assertTrue(caches.size() == 3); + Assert.assertTrue(caches.contains("c1")); + Assert.assertTrue(caches.contains("c2")); + Assert.assertTrue(caches.contains("c3")); + + // Check that the utility API for the cluster are working too + Assert.assertTrue(c.getCoordinatorAddress() != null); + Assert.assertTrue(c.getClusteredControllers() != null); + // This a one man-show + Assert.assertTrue(c.getClusteredControllers().size() == 1); + Assert.assertTrue(c.getMyAddress() != null); + // Make sure i'm the coordinator + Assert.assertTrue(c.amICoordinator()); + + // Now destroy some caches make sure they are gone + c.destroyCache("c1"); + Assert.assertTrue(!c.existCache("c1")); + caches = c.getCacheList(); + Assert.assertTrue(caches.size() == 2); + + // Now recreate the cache, make sure a different one is + // retrieved, which should be empty + try { + c1 = (ConcurrentMap) c.createCache("c1", null); + } catch (CacheExistException cee) { + // This exception should be raised because the cache + // already exists + Assert.assertTrue(true); + } catch (CacheConfigException cce) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } + c1 = (ConcurrentMap) c.getCache("c1"); + Assert.assertTrue(c1 != null); + Assert.assertTrue(c1.keySet().size() == 0); + caches = c.getCacheList(); + Assert.assertTrue(caches.size() == 3); + + // Now destroy the cache manager and make sure things are + // clean + cm.destroy(); + caches = c.getCacheList(); + Assert.assertTrue(caches.size() == 0); + + // Now to re-create two caches and make sure they exists, but + // are different than in previous life + try { + c2 = (ConcurrentMap) c.createCache("c2", null); + c3 = (ConcurrentMap) c.createCache("c3", null); + } catch (CacheExistException cee) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } catch (CacheConfigException cce) { + // Don't expect this assertion, so if happens signal a + // failure in the testcase + Assert.assertTrue(false); + } + Assert.assertTrue(c2 != null); + Assert.assertTrue(c3 != null); + caches = c.getCacheList(); + Assert.assertTrue(caches.size() == 2); + Assert.assertTrue(c2.keySet().size() == 0); + Assert.assertTrue(c3.keySet().size() == 0); + } +} diff --git a/opendaylight/clustering/test/pom.xml b/opendaylight/clustering/test/pom.xml new file mode 100644 index 0000000000..7834a65e27 --- /dev/null +++ b/opendaylight/clustering/test/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + org.opendaylight.controller + clustering.test + 0.4.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.slf4j, + javax.transaction, + org.eclipse.osgi.framework.console, + ch.qos.logback.classic, + org.opendaylight.controller.clustering.services + + + OSGI-INF/component.xml + + + + + + + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass.java new file mode 100644 index 0000000000..076ec05e32 --- /dev/null +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.clustering.test.internal; + +import java.io.Serializable; + +public class ComplexClass implements IComplex, Serializable { + private String identity; + + public ComplexClass(String i) { + this.identity = i; + } + + @Override + public String whoAmI() { + return ("ComplexClass_" + this.identity); + } + + @Override + public void IAm(String s) { + this.identity = s; + } +} diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass1.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass1.java new file mode 100644 index 0000000000..fda2ff10aa --- /dev/null +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass1.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.clustering.test.internal; + +import java.io.Serializable; + +public class ComplexClass1 implements IComplex, Serializable { + private String identity; + + public ComplexClass1(String i) { + this.identity = i; + } + + @Override + public String whoAmI() { + return ("ComplexClass1_" + this.identity); + } + + @Override + public void IAm(String s) { + this.identity = s; + } +} diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexContainer.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexContainer.java new file mode 100644 index 0000000000..adc062d4c4 --- /dev/null +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexContainer.java @@ -0,0 +1,49 @@ + +/* + * 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.controller.clustering.test.internal; + +import java.io.Serializable; + +public class ComplexContainer implements Serializable { + private IComplex f; + private IComplex f1; + private Integer state; + + public ComplexContainer(String i, Integer s) { + this.state = s; + this.f = new ComplexClass(i); + this.f1 = new ComplexClass1(i); + } + + public String getIdentity() { + if (this.f != null && this.f1 != null) { + return ("[" + f.whoAmI() + "]-[" + f1.whoAmI() + "]"); + } + return ""; + } + + public void setIdentity(String i) { + if (this.f != null) { + this.f.IAm(i); + } + if (this.f1 != null) { + this.f1.IAm(i); + } + } + + public Integer getState() { + return this.state; + } + + @Override + public String toString() { + return ("{ID:" + this.getIdentity() + ",STATE:" + this.state + "}"); + } +} diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/IComplex.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/IComplex.java new file mode 100644 index 0000000000..c1d5c31726 --- /dev/null +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/IComplex.java @@ -0,0 +1,16 @@ + +/* + * 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.controller.clustering.test.internal; + +public interface IComplex { + String whoAmI(); + + void IAm(String s); +} diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/LoggingListener.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/LoggingListener.java new file mode 100644 index 0000000000..4f5d432832 --- /dev/null +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/LoggingListener.java @@ -0,0 +1,40 @@ + +/* + * 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.controller.clustering.test.internal; + +import org.opendaylight.controller.clustering.services.IGetUpdates; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LoggingListener implements IGetUpdates { + protected static Logger logger = LoggerFactory + .getLogger(LoggingListener.class); + + @Override + public void entryCreated(Integer key, String containerName, + String cacheName, boolean originLocal) { + logger.debug(" Cache entry with key " + key + " created in cache " + + cacheName); + } + + @Override + public void entryUpdated(Integer key, StringContainer new_value, + String containerName, String cacheName, boolean originLocal) { + logger.debug(" Cache entry with key " + key + " modified to value " + + new_value + " in cache " + cacheName); + } + + @Override + public void entryDeleted(Integer key, String containerName, + String cacheName, boolean originLocal) { + logger.debug(" Cache entry with key " + key + " removed in cache " + + cacheName); + } +} diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/SimpleClient.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/SimpleClient.java new file mode 100644 index 0000000000..3e9717fa62 --- /dev/null +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/SimpleClient.java @@ -0,0 +1,646 @@ + +/* + * 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.controller.clustering.test.internal; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +import org.eclipse.osgi.framework.console.CommandInterpreter; +import org.eclipse.osgi.framework.console.CommandProvider; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.CacheListenerAddException; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.clustering.services.IGetUpdates; +import org.opendaylight.controller.clustering.services.IListenRoleChange; +import org.opendaylight.controller.clustering.services.ListenRoleChangeAddException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SimpleClient implements CommandProvider { + protected static Logger logger = LoggerFactory + .getLogger(SimpleClient.class); + IClusterServices icluster; + DoListenRoleChanged doListen; + + public void _tbegin(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + try { + this.icluster.tbegin(); + ci.println("Transaction Open " + + this.icluster.tgetTransaction().toString()); + } catch (Exception e) { + ci.println("Caught exception during transaction begin: " + e); + } + } + + public void _tcommit(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + try { + ci.println("Committing transaction ....." + + this.icluster.tgetTransaction().toString()); + this.icluster.tcommit(); + ci.println("Transaction Committed"); + } catch (Exception e) { + ci.println("Caught exception during transaction commit: " + e); + } + } + + public void _trollback(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + try { + ci.println("Rolling back transaction ....." + + this.icluster.tgetTransaction().toString()); + this.icluster.trollback(); + ci.println("Transaction Rolled Back"); + } catch (Exception e) { + ci.println("Caught exception during transaction rollback: " + e); + } + } + + public void _cacheinfo(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + if (!this.icluster.existCache(containerName, cacheName)) { + ci.println("\tCache " + cacheName + " doesn't exists"); + return; + } + ci.println("\tInfo for cache " + cacheName + " on container " + + containerName); + Properties p = this.icluster.getCacheProperties(containerName, + cacheName); + if (p != null) { + for (String key : p.stringPropertyNames()) { + ci.println("\t\t" + key + " = " + p.getProperty(key)); + } + } + } + + public void _setLogLevel(CommandInterpreter ci) { + String loggerName = ci.nextArgument(); + if (loggerName == null) { + ci.println("Logger Name not supplied"); + return; + } + String loggerLevel = ci.nextArgument(); + if (loggerLevel == null) { + ci.println("Logger Level not supplied"); + return; + } + + ch.qos.logback.classic.Logger l = (ch.qos.logback.classic.Logger) LoggerFactory + .getLogger(loggerName); + ch.qos.logback.classic.Level level = ch.qos.logback.classic.Level + .toLevel(loggerLevel); + if (level == null) { + ci.println("Level not understood"); + return; + } + l.setLevel(level); + } + + private String retrieveLogLevel(ch.qos.logback.classic.Logger l) { + if (l == null) { + return ("Logger not supplied"); + } + ch.qos.logback.classic.Level level = l.getLevel(); + if (level == null) { + return ("Logger " + l.getName() + " at unknown level"); + } else { + return ("Logger " + l.getName() + " at level " + l.getLevel() + .toString()); + } + } + + public void _getLogLevel(CommandInterpreter ci) { + String loggerName = ci.nextArgument(); + ch.qos.logback.classic.LoggerContext lc = (ch.qos.logback.classic.LoggerContext) LoggerFactory + .getILoggerFactory(); + if (lc != null) { + for (ch.qos.logback.classic.Logger l : lc.getLoggerList()) { + if (loggerName == null || l.getName().startsWith(loggerName)) { + ci.println(retrieveLogLevel(l)); + } + } + } + } + + public void _create(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + try { + if (cacheName.startsWith("T-")) { + this.icluster.createCache(containerName, cacheName, EnumSet + .of(IClusterServices.cacheMode.TRANSACTIONAL)); + } else { + this.icluster.createCache(containerName, cacheName, EnumSet + .of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + } + } catch (CacheExistException ce) { + ci + .println("\nCache already exits - destroy and recreate if needed"); + return; + } catch (CacheConfigException cfe) { + ci.println("\nCache configured with contrasting parameters"); + return; + } + + if (this.icluster.existCache(containerName, cacheName)) { + ci.println(cacheName + " has been created on container " + + containerName); + } + } + + public void _destroy(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + if (this.icluster.existCache(containerName, cacheName)) { + this.icluster.destroyCache(containerName, cacheName); + ci.println(cacheName + " has been destroyed"); + } + } + + public void _listen(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + try { + this.icluster.addListener(containerName, cacheName, + new LoggingListener()); + ci.println("cache " + cacheName + " on container " + containerName + + " is begin monitored for updates"); + } catch (CacheListenerAddException clae) { + ci.println("Couldn't attach the listener to cache " + cacheName + + " on container " + containerName); + } + } + + public void _unlisten(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + + Set> listeners = this.icluster.getListeners( + containerName, cacheName); + for (IGetUpdates l : listeners) { + this.icluster.removeListener(containerName, cacheName, l); + } + ci.println(cacheName + " is no longer being monitored for updates"); + } + + public void _listcaches(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + + // For user's convenience, let's return the sorted cache list + List sortedCacheList = new ArrayList(this.icluster + .getCacheList(containerName)); + java.util.Collections.sort(sortedCacheList); + for (String cacheName : sortedCacheList) { + ci.println("\t" + cacheName); + } + } + + public void _put(CommandInterpreter ci) { + ConcurrentMap c; + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + String sKey = ci.nextArgument(); + String sValue = ci.nextArgument(); + if (sKey == null) { + ci.println("Key not supplied"); + return; + } + if (sValue == null) { + ci.println("Value not supplied"); + return; + } + Integer key = null; + try { + key = Integer.valueOf(sKey); + } catch (NumberFormatException nfe) { + ci.println("Key is not a valid integer: " + sKey); + } + + c = (ConcurrentMap) this.icluster.getCache( + containerName, cacheName); + if (c != null) { + ci.println("\nAdd mapping " + key + " = " + sValue); + c.put(key, new StringContainer(sValue)); + } else { + ci.println("Cache " + cacheName + " on container " + containerName + + " not existant!"); + } + } + + public void _remove(CommandInterpreter ci) { + ConcurrentMap c; + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + String sKey = ci.nextArgument(); + if (sKey == null) { + ci.println("Key not supplied"); + return; + } + Integer key = null; + try { + key = Integer.valueOf(sKey); + } catch (NumberFormatException nfe) { + ci.println("Key is not a valid integer: " + sKey); + } + c = (ConcurrentMap) this.icluster.getCache( + containerName, cacheName); + if (c != null) { + ci.println("\nDelete key " + key); + c.remove(key); + } else { + ci.println("Cache " + cacheName + " on container " + containerName + + " not existant!"); + } + } + + public void _dumper(CommandInterpreter ci) { + ConcurrentMap c; + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + c = (ConcurrentMap) this.icluster.getCache(containerName, cacheName); + if (c != null) { + for (Object e : c.entrySet()) { + Map.Entry entry = (Map.Entry) e; + Object v = entry.getValue(); + String res = ""; + if (v != null) { + res = v.toString(); + } + ci.println("Element " + entry.getKey() + "(hashCode=" + + entry.getKey().hashCode() + ") has value = (" + res + + ")"); + } + } else { + ci.println("Cache " + cacheName + " on container " + containerName + + " not existant!"); + } + } + + public void _get(CommandInterpreter ci) { + ConcurrentMap c; + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + String sKey = ci.nextArgument(); + if (sKey == null) { + ci.println("Key not supplied"); + return; + } + Integer key = null; + try { + key = Integer.valueOf(sKey); + } catch (NumberFormatException nfe) { + ci.println("Key is not a valid integer: " + sKey); + } + c = (ConcurrentMap) this.icluster.getCache( + containerName, cacheName); + if (c != null) { + ci.println("\nGet key (" + key + ")=(" + c.get(key) + ")"); + } else { + ci.println("Cache " + cacheName + " on container " + containerName + + " not existant!"); + } + } + + public void _getRole(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String role = "Active"; + if (this.icluster.amIStandby()) { + role = "Standby"; + } + ci.println("My role is: " + role); + } + + public void _getActive(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + ci.println("Current active address is " + + this.icluster.getActiveAddress()); + } + + public void _listenActive(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + this.doListen = new DoListenRoleChanged(); + try { + this.icluster.listenRoleChange(this.doListen); + } catch (ListenRoleChangeAddException e) { + ci.println("Exception while registering the listener"); + return; + } + ci.println("Register listenRoleChanges"); + } + + public void _unlistenActive(CommandInterpreter ci) { + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + if (this.doListen != null) { + this.icluster.unlistenRoleChange(this.doListen); + ci.println("Unregistered Active notifications"); + } + } + + class DoListenRoleChanged implements IListenRoleChange { + public void newActiveAvailable() { + logger.debug("New Active is available"); + } + } + + public void _putComplex(CommandInterpreter ci) { + ConcurrentMap c; + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + String key = ci.nextArgument(); + if (key == null) { + ci.println("Key not supplied (String)"); + return; + } + String valueIdentity = ci.nextArgument(); + if (valueIdentity == null) { + ci.println("Value for Identity not supplied (String)"); + return; + } + String sValueState = ci.nextArgument(); + if (sValueState == null) { + ci.println("Value for State not supplied (Integer)"); + return; + } + Integer valueState = null; + try { + valueState = Integer.valueOf(sValueState); + } catch (NumberFormatException nfe) { + ci.println("Value State is not a valid integer: " + sValueState); + return; + } + c = (ConcurrentMap) this.icluster + .getCache(containerName, cacheName); + if (c != null) { + c.put(new StringContainer(key), new ComplexContainer(valueIdentity, + valueState)); + ci.println("\nPut in key (" + key + ")={String:" + valueIdentity + + ",Integer:" + valueState + "}"); + } else { + ci.println("Cache " + cacheName + " on container " + containerName + + " not existant!"); + } + } + + public void _updateComplex(CommandInterpreter ci) { + ConcurrentMap c; + if (this.icluster == null) { + ci.println("\nNo Clustering services available"); + return; + } + String containerName = ci.nextArgument(); + if (containerName == null) { + ci.println("containerName not supplied"); + return; + } + String cacheName = ci.nextArgument(); + if (cacheName == null) { + ci.println("Cache not supplied"); + return; + } + String key = ci.nextArgument(); + if (key == null) { + ci.println("Key not supplied (String)"); + return; + } + String valueIdentity = ci.nextArgument(); + if (valueIdentity == null) { + ci.println("Value for Identity not supplied (String)"); + return; + } + c = (ConcurrentMap) this.icluster + .getCache(containerName, cacheName); + if (c != null) { + StringContainer k = new StringContainer(key); + ComplexContainer v = c.get(k); + if (v != null) { + v.setIdentity(valueIdentity); + ci.println("\nUpdate key (" + key + ")={String:" + + valueIdentity + "}"); + + // IMPORTANT ON UPDATING ANY FIELD OF THE CHILD MAKE + // SURE TO PUT THE NEW VALUE IN THE CACHE ELSE THE + // VALUE WILL NOT PROPAGATE!! + c.put(k, v); + } else { + ci.println("\nCannot Update key (" + key + + ") doesn't exist in the database"); + } + } else { + ci.println("Cache " + cacheName + " on container " + containerName + + " not existant!"); + } + } + + public void setIClusterServices(IClusterServices i) { + this.icluster = i; + logger.debug("IClusterServices set"); + } + + public void unsetIClusterServices(IClusterServices i) { + if (this.icluster == i) { + this.icluster = null; + logger.debug("IClusterServices UNset"); + } + } + + public void startUp() { + logger.debug("Started clustering test plugin"); + } + + public void shutDown() { + logger.debug("Stopped clustering test plugin"); + } + + @Override + public String getHelp() { + StringBuffer help = new StringBuffer(); + help.append("---Clustering Service Testing---\n"); + help.append("\tput - Put a key,value in the cache\n"); + help.append("\tremove - Delete a key from the cache\n"); + help.append("\tget - Get a key from the cache\n"); + help.append("\tdumper - Dump the cache\n"); + help + .append("\tcacheinfo - Dump the configuration for a cache\n"); + help.append("\ttbegin - Transaction begin\n"); + help.append("\ttcommit - Transaction Commit\n"); + help.append("\ttrollback - Transaction Rollback\n"); + help.append("\tlistcaches - List all the Caches\n"); + help.append("\tlisten - Listen to cache updates\n"); + help.append("\tunlisten - UNListen to cache updates\n"); + help.append("\tlistenActive - Listen to Active updates\n"); + help.append("\tunlistenActive - UNListen to Active updates\n"); + help.append("\tdestroy - Destroy a cache\n"); + help.append("\tcreate - Create a cache\n"); + help.append("\tgetRole - Tell if active or standby\n"); + help.append("\tgetActive - Report the IP address of Active\n"); + help + .append("\tputComplex - Fill a more complex data structure\n"); + help + .append("\tupdateComplex - Update the value of a more complex data structure\n"); + help + .append("\tgetLogLevel - Get the loglevel for the logger specified\n"); + help + .append("\tsetLogLevel - Set the loglevel for the logger specified\n"); + return help.toString(); + } +} diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/StringContainer.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/StringContainer.java new file mode 100644 index 0000000000..39ef1b0e29 --- /dev/null +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/StringContainer.java @@ -0,0 +1,55 @@ + +/* + * 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.controller.clustering.test.internal; + +import java.io.Serializable; + +public class StringContainer implements Serializable { + private String mystring; + + public StringContainer() { + this.mystring = null; + } + + public StringContainer(String s) { + setMystring(s); + } + + public String getMystring() { + return mystring; + } + + public void setMystring(String mystring) { + this.mystring = mystring; + } + + // Return the hashCode of the containing string + @Override + public int hashCode() { + if (this.mystring != null) { + return this.mystring.hashCode(); + } + return 0; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof StringContainer) { + StringContainer o = (StringContainer) obj; + return this.mystring.equals(o.getMystring()); + } + return false; + } + + @Override + public String toString() { + return "{" + this.mystring + "}"; + } +} diff --git a/opendaylight/clustering/test/src/main/resources/OSGI-INF/component.xml b/opendaylight/clustering/test/src/main/resources/OSGI-INF/component.xml new file mode 100644 index 0000000000..df0e388e61 --- /dev/null +++ b/opendaylight/clustering/test/src/main/resources/OSGI-INF/component.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/opendaylight/clustering/test/src/test/java/org/opendaylight/controller/clustering/test/internal/TestClusteringTest.java b/opendaylight/clustering/test/src/test/java/org/opendaylight/controller/clustering/test/internal/TestClusteringTest.java new file mode 100644 index 0000000000..fa00c7f455 --- /dev/null +++ b/opendaylight/clustering/test/src/test/java/org/opendaylight/controller/clustering/test/internal/TestClusteringTest.java @@ -0,0 +1,67 @@ + +/* + * 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.controller.clustering.test.internal; + + +import org.junit.Assert; +import org.junit.Test; + +import junit.framework.TestCase; + +public class TestClusteringTest extends TestCase { + + @Test + public void testComplexClass() { + ComplexClass cc = new ComplexClass("cplxc1"); + Assert.assertTrue(cc.whoAmI().equals("ComplexClass_cplxc1")); + cc.IAm("cplxc2"); + Assert.assertTrue(cc.whoAmI().equals("ComplexClass_cplxc2")); + } + + @Test + public void testComplexClass1() { + ComplexClass1 cc1 = new ComplexClass1("cplxc1a"); + Assert.assertTrue(cc1.whoAmI().equals("ComplexClass1_cplxc1a")); + cc1.IAm("cplxc1b"); + Assert.assertTrue(cc1.whoAmI().equals("ComplexClass1_cplxc1b")); + } + + + @Test + public void testComplexContainer() { + ComplexContainer cplxcontnr1 = new ComplexContainer("cct1", 5); + Assert.assertTrue(cplxcontnr1.getIdentity().equals("[ComplexClass_cct1]-[ComplexClass1_cct1]")); + Assert.assertTrue(cplxcontnr1.getState() == 5); + + cplxcontnr1.setIdentity("cct2"); + Assert.assertTrue(cplxcontnr1.getIdentity().equals("[ComplexClass_cct2]-[ComplexClass1_cct2]")); + + Assert.assertTrue(cplxcontnr1.toString().equals( + "{ID:[ComplexClass_cct2]-[ComplexClass1_cct2],STATE:5}")); + } + + @Test + public void testStringContainer() { + StringContainer strcontainer1 = new StringContainer(); + Assert.assertTrue(strcontainer1.getMystring() == null); + Assert.assertTrue(strcontainer1.hashCode() == 0); + + StringContainer strcontainer2 = new StringContainer("foo"); + Assert.assertTrue(strcontainer2.getMystring() != null); + Assert.assertTrue(strcontainer2.hashCode() != 0); + + strcontainer1.setMystring("foo"); + Assert.assertTrue(strcontainer2.equals(strcontainer1)); + + Assert.assertTrue(strcontainer2.toString().equals("{foo}")); + } + + +} diff --git a/opendaylight/commons/opendaylight/logback.xml b/opendaylight/commons/opendaylight/logback.xml new file mode 100644 index 0000000000..043ceef329 --- /dev/null +++ b/opendaylight/commons/opendaylight/logback.xml @@ -0,0 +1,12 @@ + + + + + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml new file mode 100644 index 0000000000..39f100d6dc --- /dev/null +++ b/opendaylight/commons/opendaylight/pom.xml @@ -0,0 +1,831 @@ + + + 4.0.0 + + 3.0 + + + + sitebuildsettings + sitebuildsettings + 1.0.0-SNAPSHOT + ../../../sitebuildsettings-pom.xml + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + pom + + + 3.2 + 2.6 + UTF-8 + 2.3.2 + 2.13 + 3.0.0 + 1.5.0 + 1.26.2 + ${user.name}-private-view + org.openflow.openflowj,net.sf.jung2 + 1.0.9 + 1.7.2 + 1.9.8 + 3.1.3.RELEASE + 3.1.3.RELEASE + 1.17 + 3.6.0.RELEASE + 2.2.0.RELEASE + + + + + central2 + central2 + ${nexusproxy}/repositories/central2/ + + + + + + viewbuild + + true + + + ${project.version} + + + + jenkins + + + BUILDSUFFIX + + + + ${BUILDSUFFIX} + + + + fastreassembly + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.4 + + + copyfastreassembly + install + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + ${project.groupId}.${project.artifactId}-${project.version}.jar + + + ${fastreassembly.directory} + + + + + + + + + + + + + + ebr-bundles-release + ebr-bundles-release + ${nexusproxy}/repositories/ebr-bundles-release/ + + + + + ebr-bundles-external + ebr-bundles-external + ${nexusproxy}/repositories/ebr-bundles-external/ + + + + + central2 + central2 + ${nexusproxy}/repositories/central2/ + + + + + central + central + ${nexusproxy}/repositories/central/ + + + + + ops4j-releases + ops4j-releases + ${nexusproxy}/repositories/ops4j-releases/ + + + + thirdparty + thirdparty + ${nexusproxy}/repositories/thirdparty/ + + + + + jboss.releases + jboss.releases + ${nexusproxy}/repositories/jboss.releases/ + + + + opendaylight-release + opendaylight-release + ${nexusproxy}/repositories/opendaylight.release/ + + + + opendaylight-snapshot + opendaylight-snapshot + ${nexusproxy}/repositories/opendaylight.snapshot/ + + + + + + ${opendaylightID}-release + ${nexusproxy}/repositories/opendaylight.release/ + + + + ${opendaylightID}-snapshot + ${nexusproxy}/repositories/opendaylight.snapshot/ + + + + website + ${sitedeploy} + + + + + true + ${project.build.directory}/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + ${projectinfo} + + false + false + + + + + index + project-team + license + mailing-list + plugin-management + cim + issue-tracking + scm + summary + + + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + true + true + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.10 + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + org.jboss.apiviz.APIviz + + org.jboss.apiviz + apiviz + 1.3.2.GA + + ${project.artifactId}-${build.suffix} + true + UTF-8 + UTF-8 + UTF-8 + true + true + true + true + *.internal:edu.uci.* + + + + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + + set-system-properties + + + + + logback.configurationFile + ${project.parent.relativePath}/logback.xml + + + + + + + + com.googlecode.maven-java-formatter-plugin + maven-java-formatter-plugin + 0.3.1 + + 1.6 + 1.6 + 1.6 + ${project.parent.relativePath}/sun_coding_style.xml + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.codehaus.mojo + properties-maven-plugin + [0.0,) + + set-system-properties + + + + + + + + + + + + org.codehaus.enunciate + maven-enunciate-plugin + ${enunciate.version} + + enunciate.xml + + + + + docs + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${compiler.version} + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + org.jboss.apiviz.APIviz + + org.jboss.apiviz + apiviz + 1.3.2.GA + + ${project.artifactId}-${build.suffix} + true + UTF-8 + UTF-8 + UTF-8 + true + true + true + true + net.sf.jnetlib.*:cern.*:corejava:*.internal:edu.uci.* + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + true + true + target/apidocs + + + + + + + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + log4j-over-slf4j + ${slf4j.version} + + + ch.qos.logback + logback-core + ${logback.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.codehaus.jackson + jackson-mapper-asl + ${jackson.version} + + + org.codehaus.jackson + jackson-core-asl + ${jackson.version} + + + org.codehaus.jackson + jackson-jaxrs + ${jackson.version} + + + org.codehaus.jettison + jettison + 1.3.3 + + + commons-io + commons-io + 2.3 + + + commons-fileupload + commons-fileupload + 1.2.2 + + + equinoxSDK381 + javax.servlet + 3.0.0.v201112011016 + + + equinoxSDK381 + javax.servlet.jsp + 2.2.0.v201112011158 + + + equinoxSDK381 + org.eclipse.equinox.ds + 1.4.0.v20120522-1841 + + + equinoxSDK381 + org.eclipse.equinox.util + 1.0.400.v20120522-2049 + + + equinoxSDK381 + org.eclipse.osgi.services + 3.3.100.v20120522-1822 + + + equinoxSDK381 + org.eclipse.osgi + 3.8.1.v20120830-144521 + + + equinoxSDK381 + org.apache.felix.gogo.command + 0.8.0.v201108120515 + + + equinoxSDK381 + org.apache.felix.gogo.runtime + 0.8.0.v201108120515 + + + equinoxSDK381 + org.apache.felix.gogo.shell + 0.8.0.v201110170705 + + + equinoxSDK381 + org.eclipse.equinox.cm + 1.0.400.v20120522-1841 + + + equinoxSDK381 + org.eclipse.equinox.console + 1.0.0.v20120522-1841 + + + equinoxSDK381 + org.eclipse.equinox.launcher + 1.3.0.v20120522-1813 + + + + geminiweb + org.eclipse.gemini.web.core + ${geminiweb.version} + + + geminiweb + org.eclipse.gemini.web.extender + ${geminiweb.version} + + + geminiweb + org.eclipse.gemini.web.tomcat + ${geminiweb.version} + + + geminiweb + org.eclipse.virgo.kernel.equinox.extensions + ${virgo.version} + + + geminiweb + org.eclipse.virgo.util.common + ${virgo.version} + + + geminiweb + org.eclipse.virgo.util.io + ${virgo.version} + + + geminiweb + org.eclipse.virgo.util.math + ${virgo.version} + + + geminiweb + org.eclipse.virgo.util.osgi + ${virgo.version} + + + geminiweb + org.eclipse.virgo.util.osgi.manifest + ${virgo.version} + + + geminiweb + org.eclipse.virgo.util.parser.manifest + ${virgo.version} + + + org.apache.felix + org.apache.felix.dependencymanager + 3.1.0 + + + org.apache.felix + org.apache.felix.dependencymanager.shell + 3.0.1 + + + com.google.code.gson + gson + 2.1 + compile + + + org.jboss.spec.javax.transaction + jboss-transaction-api_1.1_spec + 1.0.1.Final + + + org.apache.felix + org.apache.felix.fileinstall + 3.1.6 + + + org.apache.commons + commons-lang3 + 3.1 + + + virgomirror + org.eclipse.jdt.core.compiler.batch + 3.8.0.I20120518-2145 + + + eclipselink + javax.persistence + 2.0.4.v201112161009 + + + orbit + javax.activation + 1.1.0.v201211130549 + + + orbit + javax.annotation + 1.1.0.v201209060031 + + + orbit + javax.ejb + 3.1.1.v201204261316 + + + orbit + javax.el + 2.2.0.v201108011116 + + + orbit + javax.mail.glassfish + 1.4.1.v201108011116 + + + orbit + javax.xml.rpc + 1.1.0.v201005080400 + + + orbit + org.apache.catalina + 7.0.32.v201211201336 + + + orbit + org.apache.catalina.ha + 7.0.32.v201211201952 + + + orbit + org.apache.catalina.tribes + 7.0.32.v201211201952 + + + orbit + org.apache.coyote + 7.0.32.v201211201952 + + + orbit + org.apache.el + 7.0.32.v201211081135 + + + orbit + org.apache.jasper + 7.0.32.v201211201952 + + + orbit + org.apache.juli.extras + 7.0.32.v201211081135 + + + orbit + org.apache.tomcat.api + 7.0.32.v201211081135 + + + orbit + org.apache.tomcat.util + 7.0.32.v201211201952 + + + orbit + javax.servlet.jsp.jstl + 1.2.0.v201105211821 + + + orbit + javax.servlet.jsp.jstl.impl + 1.2.0.v201210211230 + + + + org.ops4j.pax.exam + pax-exam-container-native + ${exam.version} + test + + + org.ops4j.pax.exam + pax-exam-junit4 + ${exam.version} + test + + + org.ops4j.pax.exam + pax-exam-link-mvn + ${exam.version} + test + + + org.ops4j.pax.url + pax-url-aether + ${url.version} + test + + + org.springframework + org.springframework.asm + ${spring.version} + + + org.springframework + org.springframework.aop + ${spring.version} + + + org.springframework + org.springframework.context + ${spring.version} + + + org.springframework + org.springframework.context.support + ${spring.version} + + + org.springframework + org.springframework.core + ${spring.version} + + + org.springframework + org.springframework.beans + ${spring.version} + + + org.springframework + org.springframework.expression + ${spring.version} + + + org.springframework + org.springframework.web + ${spring.version} + + + org.aopalliance + com.springsource.org.aopalliance + 1.0.0 + + + org.springframework + org.springframework.web.servlet + ${spring.version} + + + + org.springframework.security + spring-security-config + ${spring-security.version} + + + org.springframework.security + spring-security-core + ${spring-security.version} + + + org.springframework.security + spring-security-web + ${spring-security.version} + + + org.springframework.security + spring-security-taglibs + ${spring-security.version} + + + org.springframework + org.springframework.transaction + ${spring-security.version} + + + + org.ow2.chameleon.management + chameleon-mbeans + 1.0.0 + + + + com.sun.jersey + jersey-core + ${jersey.version} + + + com.sun.jersey + jersey-server + ${jersey.version} + + + com.sun.jersey + jersey-client + ${jersey.version} + + + com.sun.jersey + jersey-json + ${jersey.version} + + + com.sun.jersey.contribs + jersey-spring + ${jersey.version} + + + org.springframework + spring + + + org.springframework + spring-aop + + + org.springframework + spring-core + + + org.springframework + spring-web + + + org.springframework + spring-beans + + + org.springframework + spring-context + + + + + diff --git a/opendaylight/commons/opendaylight/sun_coding_style.xml b/opendaylight/commons/opendaylight/sun_coding_style.xml new file mode 100644 index 0000000000..f4516b913d --- /dev/null +++ b/opendaylight/commons/opendaylight/sun_coding_style.xml @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/opendaylight-application.launch b/opendaylight/distribution/opendaylight/opendaylight-application.launch new file mode 100644 index 0000000000..5de9baee2f --- /dev/null +++ b/opendaylight/distribution/opendaylight/opendaylight-application.launch @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/opendaylight-assembleit-fast.launch b/opendaylight/distribution/opendaylight/opendaylight-assembleit-fast.launch new file mode 100644 index 0000000000..b6a2b494d8 --- /dev/null +++ b/opendaylight/distribution/opendaylight/opendaylight-assembleit-fast.launch @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/opendaylight-assembleit-noclean.launch b/opendaylight/distribution/opendaylight/opendaylight-assembleit-noclean.launch new file mode 100644 index 0000000000..9de0422bbe --- /dev/null +++ b/opendaylight/distribution/opendaylight/opendaylight-assembleit-noclean.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/opendaylight-assembleit-skiput.launch b/opendaylight/distribution/opendaylight/opendaylight-assembleit-skiput.launch new file mode 100644 index 0000000000..de02206a5d --- /dev/null +++ b/opendaylight/distribution/opendaylight/opendaylight-assembleit-skiput.launch @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/opendaylight-assembleit-sonar.launch b/opendaylight/distribution/opendaylight/opendaylight-assembleit-sonar.launch new file mode 100644 index 0000000000..077592ca30 --- /dev/null +++ b/opendaylight/distribution/opendaylight/opendaylight-assembleit-sonar.launch @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/opendaylight-assembleit.launch b/opendaylight/distribution/opendaylight/opendaylight-assembleit.launch new file mode 100644 index 0000000000..550de32f94 --- /dev/null +++ b/opendaylight/distribution/opendaylight/opendaylight-assembleit.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/opendaylight-sonar-fast.launch b/opendaylight/distribution/opendaylight/opendaylight-sonar-fast.launch new file mode 100644 index 0000000000..6de99e1a26 --- /dev/null +++ b/opendaylight/distribution/opendaylight/opendaylight-sonar-fast.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/opendaylight-sonar.launch b/opendaylight/distribution/opendaylight/opendaylight-sonar.launch new file mode 100644 index 0000000000..a66427202b --- /dev/null +++ b/opendaylight/distribution/opendaylight/opendaylight-sonar.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml new file mode 100644 index 0000000000..3ec92d316e --- /dev/null +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + + 3.0 + + + + scm:svn:https://wwwin-svn-sjc.cisco.com/eng/csdncontroller/trunk/ + scm:svn:https://wwwin-svn-sjc.cisco.com/eng/csdncontroller/trunk/ + + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + + + + svnkit-snapshots + svnkit-snapshots + ${nexusproxy}/repositories/svnkit-snapshots/ + + + + org.opendaylight.controller + distribution.opendaylight + 0.1.0-SNAPSHOT + pom + + ../../clustering/services + ../../clustering/services_implementation + ../../clustering/stub + ../../clustering/test + ../../../third-party/openflowj + ../../../third-party/net.sf.jung2 + ../../../third-party/jersey-servlet + + + ../../sal/api + ../../sal/implementation + + + ../../logging/bridge + + + + + + org.codehaus.mojo + buildnumber-maven-plugin + 1.2 + + + validate + + create + + + + + false + false + + javasvn + + VersionUnknown + + + + com.google.code.maven-scm-provider-svnjava + maven-scm-provider-svnjava + 2.0.5 + + + org.tmatesoft.svnkit + svnkit + 1.7.4-v1 + + + org.apache.maven.scm + maven-scm-provider-svn-commons + 1.7 + + + + + maven-assembly-plugin + 2.3 + + + distro-assembly + package + + single + + + + src/assemble/bin.xml + + ${project.artifactId}-${build.suffix} + + + + + + + diff --git a/opendaylight/distribution/opendaylight/src/assemble/bin.xml b/opendaylight/distribution/opendaylight/src/assemble/bin.xml new file mode 100644 index 0000000000..3c163fdd35 --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/assemble/bin.xml @@ -0,0 +1,108 @@ + + osgipackage + + dir + zip + + false + + + + org.opendaylight.controller.thirdparty:org.openflow.openflowj + org.opendaylight.controller:clustering.stub + org.opendaylight.controller:logging.bridge + + + opendaylight/plugins + + ${module.groupId}.${module.artifactId}-${module.version}${dashClassifier?}.${module.extension} + + false + false + + + + + org.opendaylight.controller:logging.bridge + + + opendaylight/lib + + ${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} + + false + false + + + + + + opendaylight/plugins + + equinoxSDK381:org.eclipse.osgi + equinoxSDK381:org.eclipse.equinox.console + equinoxSDK381:org.eclipse.equinox.launcher + equinoxSDK381:org.eclipse.equinox.ds + equinoxSDK381:org.eclipse.equinox.util + equinoxSDK381:org.eclipse.osgi.services + virgomirror:org.eclipse.jdt.core.compiler.batch + org.apache.felix:org.apache.felix.fileinstall + geminiweb:org.eclipse.virgo.kernel.equinox.extensions + org.slf4j:slf4j-api + ch.qos.logback:logback-core + ch.qos.logback:logback-classic + + + ${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} + + false + runtime + false + + + opendaylight/lib + + equinoxSDK381:org.eclipse.osgi + equinoxSDK381:org.eclipse.equinox.console + equinoxSDK381:org.eclipse.equinox.launcher + equinoxSDK381:org.eclipse.equinox.ds + equinoxSDK381:org.eclipse.equinox.util + equinoxSDK381:org.eclipse.osgi.services + virgomirror:org.eclipse.jdt.core.compiler.batch + org.apache.felix:org.apache.felix.fileinstall + geminiweb:org.eclipse.virgo.kernel.equinox.extensions + org.slf4j:slf4j-api + ch.qos.logback:logback-core + ch.qos.logback:logback-classic + + false + + ${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} + + false + runtime + + + + + + src/main/resources/ + + + version.properties + + + opendaylight/ + + + + + + src/main/resources/version.properties + opendaylight + true + + + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini new file mode 100644 index 0000000000..1b3d1ec062 --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini @@ -0,0 +1,41 @@ +osgi.bundles=\ + reference\:file\:../lib/org.apache.felix.fileinstall-3.1.6.jar@1:start,\ + reference\:file\:../lib/org.eclipse.jdt.core.compiler.batch-3.8.0.I20120518-2145.jar@1:start,\ + reference\:file\:../lib/org.eclipse.equinox.ds-1.4.0.v20120522-1841.jar@2:start,\ + reference\:file\:../lib/org.eclipse.equinox.util-1.0.400.v20120522-2049.jar@2:start,\ + reference\:file\:../lib/org.eclipse.osgi.services-3.3.100.v20120522-1822@2:start,\ + reference\:file\:../lib/org.eclipse.equinox.console-1.0.0.v20120522-1841.jar@start,\ + reference\:file\:../lib/slf4j-api-1.7.2.jar@1:start,\ + reference\:file\:../lib/logback-classic-1.0.9.jar@1:start,\ + reference\:file\:../lib/logback-core-1.0.9.jar@1:start,\ + reference\:file\:../lib/logging.bridge-0.4.0-SNAPSHOT@1:start + +# Set Default start level for framework +osgi.bundles.defaultStartLevel=4 +# Extra packages to import from the boot class loader +org.osgi.framework.system.packages.extra=sun.reflect,sun.reflect.misc,sun.misc +# This is not Eclipse App +eclipse.ignoreApp=true +# Don't shutdown equinox if the eclipse App has ended, +# which is our case because we are not running any eclipse application +osgi.noShutdown=true +# Clean any cached data on restart of the framework +osgi.clean=true +# Extend the framework to avoid the resources to be presented with +# a URL of type bundleresource: but to be presented as file: +osgi.hook.configurators.include=org.eclipse.virgo.kernel.equinox.extensions.hooks.ExtensionsHookConfigurator +# Directory from where the fileinstall will monitor for new bundles +felix.fileinstall.dir=./plugins +# Immediately learn new bundles at startup +felix.fileinstall.noInitialDelay=true +# Auto start the bundles at level 4 +felix.fileinstall.start.level=4 +# Avoid to auto-install following bundles, that means those need +# to be started manually or in other way like osgi.bundles +felix.fileinstall.filter=^(?!org.apache.felix.fileinstall).* + +# logback configuration +logback.configurationFile=configuration/logback.xml + +# Embedded Tomcat configuration File +org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/context.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/context.xml new file mode 100644 index 0000000000..85bba5a6aa --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/context.xml @@ -0,0 +1 @@ + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml new file mode 100644 index 0000000000..3c3f78889f --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml @@ -0,0 +1,55 @@ + + + + + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n + + + + logs/opendaylight.log + + + logs/opendaylight.%d.log.zip + 1 + + + + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/tomcat-server.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/tomcat-server.xml new file mode 100644 index 0000000000..42199b774c --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/tomcat-server.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/run.bat b/opendaylight/distribution/opendaylight/src/main/resources/run.bat new file mode 100644 index 0000000000..79a00f33e4 --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/run.bat @@ -0,0 +1,22 @@ +@ECHO OFF +SETLOCAL +SETLOCAL ENABLEDELAYEDEXPANSION +IF EXIST "%JAVA_HOME%" ( + set basedir=%~dp0 +REM Now set the classpath: + set cp="!basedir!lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar;!basedir!lib\org.eclipse.virgo.kernel.equinox.extensions-3.6.0.RELEASE.jar;!basedir!lib\org.eclipse.equinox.launcher-1.3.0.v20120522-1813.jar" + +REM Now set framework classpath + set fwcp="file:\!basedir!lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar,file:\!basedir!lib\org.eclipse.virgo.kernel.equinox.extensions-3.6.0.RELEASE.jar,file:\!basedir!lib\org.eclipse.equinox.launcher-1.3.0.v20120522-1813.jar" + +REM echo cp: %cp% +REM echo fwcp: %fwcp% + +REM echo %JAVA_HOME%\bin\java.exe %* -Djava.io.tmpdir=!basedir!work\tmp -Dosgi.install.area=!basedir! -Dosgi.configuration.area=!basedir!configuration -Dosgi.frameworkClassPath=%fwcp% -Dosgi.framework=file:\!basedir!lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar -classpath %cp% org.eclipse.equinox.launcher.Main -console -consoleLog +"%JAVA_HOME%\bin\java.exe" %* -Djava.io.tmpdir="!basedir!work\tmp" -Dosgi.install.area=!basedir! -Dosgi.configuration.area="!basedir!configuration" -Dosgi.frameworkClassPath=!fwcp! -Dosgi.framework="file:\!basedir!lib\org.eclipse.osgi-3.8.1.v20120830-144521.jar" -classpath !cp! org.eclipse.equinox.launcher.Main -console -consoleLog + +) ELSE ( + ECHO JAVA_HOME environment variable is not set + PAUSE +) +ENDLOCAL \ No newline at end of file diff --git a/opendaylight/distribution/opendaylight/src/main/resources/run.sh b/opendaylight/distribution/opendaylight/src/main/resources/run.sh new file mode 100755 index 0000000000..74cadaed38 --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/run.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +[[ -z ${JAVA_HOME} ]] && echo "Need to set JAVA_HOME environment variable" && exit -1; +[[ ! -x ${JAVA_HOME}/bin/java ]] && echo "Cannot find an executable \ +JVM at path ${JAVA_HOME}/bin/java check your JAVA_HOME" && exit -1; + +platform='unknown' +unamestr=`uname` +if [[ "$unamestr" == 'Linux' ]]; then + platform='linux' +elif [[ "$unamestr" == 'Darwin' ]]; then + platform='osx' +fi + +if [[ $platform == 'linux' ]]; then + fullpath=`readlink -f $0` +elif [[ $platform == 'osx' ]]; then + TARGET_FILE=$0 + cd `dirname $TARGET_FILE` + TARGET_FILE=`basename $TARGET_FILE` + + # Iterate down a (possible) chain of symlinks + while [ -L "$TARGET_FILE" ] + do + TARGET_FILE=`readlink $TARGET_FILE` + cd `dirname $TARGET_FILE` + TARGET_FILE=`basename $TARGET_FILE` + done + + # Compute the canonicalized name by finding the physical path + # for the directory we're in and appending the target file. + PHYS_DIR=`pwd -P` + RESULT=$PHYS_DIR/$TARGET_FILE + fullpath=$RESULT +fi + +basedir=`dirname ${fullpath}` + +######################################## +# Now add to classpath the OSGi JAR +######################################## +CLASSPATH=${basedir}/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar +FWCLASSPATH=file:${basedir}/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar + +######################################## +# Now add the extensions +######################################## + +# Extension 1: this is used to be able to convert all the +# bundleresouce: URL in file: so packages that are not OSGi ready can +# still work. Notably this is the case for spring classes +CLASSPATH=${CLASSPATH}:${basedir}/lib/org.eclipse.virgo.kernel.equinox.extensions-3.6.0.RELEASE.jar +FWCLASSPATH=${FWCLASSPATH},file:${basedir}/lib/org.eclipse.virgo.kernel.equinox.extensions-3.6.0.RELEASE.jar + +######################################## +# Now add the launcher +######################################## +CLASSPATH=${CLASSPATH}:${basedir}/lib/org.eclipse.equinox.launcher-1.3.0.v20120522-1813.jar +FWCLASSPATH=${FWCLASSPATH},file:${basedir}/lib/org.eclipse.equinox.launcher-1.3.0.v20120522-1813.jar + +$JAVA_HOME/bin/java $@ \ + -Djava.io.tmpdir=${basedir}/work/tmp \ + -Dosgi.install.area=${basedir} \ + -Dosgi.configuration.area=${basedir}/configuration \ + -Dosgi.frameworkClassPath=${FWCLASSPATH} \ + -Dosgi.framework=file:${basedir}/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar \ + -classpath ${CLASSPATH} \ + org.eclipse.equinox.launcher.Main \ + -console \ + -consoleLog diff --git a/opendaylight/distribution/opendaylight/src/main/resources/version.properties b/opendaylight/distribution/opendaylight/src/main/resources/version.properties new file mode 100644 index 0000000000..90af49dfc2 --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/version.properties @@ -0,0 +1,6 @@ +org.opendaylight.controller.version = 0.1 +org.opendaylight.controller.build.scm.version = ${buildNumber} +org.opendaylight.controller.build.user = ${env.USER} +org.opendaylight.controller.build.workspace = ********** +org.opendaylight.controller.build.timestamp = ${timestamp} +org.opendaylight.controller.build.machine = ********** diff --git a/opendaylight/distribution/sdk/pom.xml b/opendaylight/distribution/sdk/pom.xml new file mode 100644 index 0000000000..51152c9ace --- /dev/null +++ b/opendaylight/distribution/sdk/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + + 3.0 + + + + scm:svn:https://wwwin-svn-sjc.cisco.com/eng/csdncontroller/trunk/ + scm:svn:https://wwwin-svn-sjc.cisco.com/eng/csdncontroller/trunk/ + + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + + + + svnkit-snapshots + svnkit-snapshots + ${nexusproxy}/repositories/svnkit-snapshots/ + + + + org.opendaylight.controller + distribution.sdk + 0.1.0-SNAPSHOT + pom + + ../../clustering/services + ../../sal/api + + + + + + org.codehaus.mojo + buildnumber-maven-plugin + 1.2 + + + validate + + create + + + + + false + false + + javasvn + + VersionUnknown + + + + com.google.code.maven-scm-provider-svnjava + maven-scm-provider-svnjava + 2.0.5 + + + org.tmatesoft.svnkit + svnkit + 1.7.4-v1 + + + org.apache.maven.scm + maven-scm-provider-svn-commons + 1.7 + + + + + maven-assembly-plugin + 2.3 + + + distro-assembly + package + + single + + + + src/assemble/bin.xml + + ${project.artifactId}-${build.suffix} + + + + + + + + + org.osgi + org.osgi.compendium + 4.2.0 + + + org.osgi + org.osgi.core + 4.3.0 + + + diff --git a/opendaylight/distribution/sdk/src/assemble/bin.xml b/opendaylight/distribution/sdk/src/assemble/bin.xml new file mode 100644 index 0000000000..bb3c6734f6 --- /dev/null +++ b/opendaylight/distribution/sdk/src/assemble/bin.xml @@ -0,0 +1,39 @@ + + package + + dir + zip + + false + + + + sdk/ + + ${module.groupId}.${module.artifactId}-${module.version}${dashClassifier?}.${module.extension} + + false + false + + + + + + sdk/ + + org.apache.felix:org.apache.felix.dependencymanager + org.osgi:org.osgi.compendium + org.osgi:org.osgi.core + org.slf4j:slf4j-api + + + ${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension} + + false + runtime + false + + + diff --git a/opendaylight/logging/bridge/pom.xml b/opendaylight/logging/bridge/pom.xml new file mode 100644 index 0000000000..ba0ace7e0e --- /dev/null +++ b/opendaylight/logging/bridge/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + org.opendaylight.controller + logging.bridge + 0.4.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.slf4j, + org.osgi.framework, + org.osgi.service.log + + + org.opendaylight.controller.logging.bridge.internal.Activator + + + + + + + diff --git a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java new file mode 100644 index 0000000000..90908ef7fa --- /dev/null +++ b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java @@ -0,0 +1,80 @@ + +/* + * 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.controller.logging.bridge.internal; + +import org.osgi.service.log.LogEntry; +import java.util.Enumeration; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.ILoggerFactory; +import org.osgi.service.log.LogReaderService; + +public class Activator implements BundleActivator { + private LogListenerImpl listener = null; + private Logger log = null; + + @Override + public void start(BundleContext context) { + // Lets trigger the resolution of the slf4j logger factory + ILoggerFactory f = LoggerFactory.getILoggerFactory(); + + // Now retrieve a logger for the bridge + log = f + .getLogger("org.opendaylight.controller.logging.bridge.OSGI2SLF4J"); + + if (this.log != null) { + this.listener = new LogListenerImpl(log); + + ServiceReference service = null; + service = context.getServiceReference(LogReaderService.class + .getName()); + if (service != null) { + LogReaderService reader = (LogReaderService) context + .getService(service); + if (reader == null) { + this.log.error("Cannot register the LogListener because " + + "cannot retrive LogReaderService"); + } + reader.addLogListener(this.listener); + // Now lets walk all the exiting messages + Enumeration entries = reader.getLog(); + if (entries != null) { + while (entries.hasMoreElements()) { + LogEntry entry = (LogEntry) entries.nextElement(); + this.listener.logged(entry); + } + } + } else { + this.log.error("Cannot register the LogListener because " + + "cannot retrive LogReaderService"); + } + } else { + System.err + .println("Could not initialize the logging bridge subsytem"); + } + } + + @Override + public void stop(BundleContext context) { + ServiceReference service = null; + service = context.getServiceReference(LogReaderService.class.getName()); + if (service != null) { + LogReaderService reader = (LogReaderService) service; + reader.removeLogListener(this.listener); + } + + this.listener = null; + this.log = null; + } +} diff --git a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/LogListenerImpl.java b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/LogListenerImpl.java new file mode 100644 index 0000000000..d3c72b962f --- /dev/null +++ b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/LogListenerImpl.java @@ -0,0 +1,43 @@ + +/* + * 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.controller.logging.bridge.internal; + +import org.osgi.service.log.LogEntry; +import org.osgi.service.log.LogListener; +import org.osgi.service.log.LogService; +import org.slf4j.Logger; + +public class LogListenerImpl implements LogListener { + private Logger logger = null; + + public LogListenerImpl(Logger l) { + this.logger = l; + } + + @Override + public void logged(LogEntry entry) { + if (this.logger != null) { + switch (entry.getLevel()) { + case LogService.LOG_DEBUG: + this.logger.debug(entry.getMessage()); + break; + case LogService.LOG_INFO: + this.logger.info(entry.getMessage()); + break; + case LogService.LOG_WARNING: + this.logger.warn(entry.getMessage()); + break; + case LogService.LOG_ERROR: + this.logger.error(entry.getMessage()); + break; + } + } + } +} diff --git a/opendaylight/sal/api/pom.xml b/opendaylight/sal/api/pom.xml new file mode 100644 index 0000000000..9d8c814d6d --- /dev/null +++ b/opendaylight/sal/api/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + org.opendaylight.controller + sal + 0.4.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.slf4j, + org.osgi.framework, + org.apache.commons.lang3.builder, + org.apache.felix.dm, + org.apache.commons.lang3.tuple, + javax.xml.bind.annotation, + javax.xml.bind.annotation.adapters + + + org.opendaylight.controller.sal.authorization, + org.opendaylight.controller.sal.action, + org.opendaylight.controller.sal.core, + org.opendaylight.controller.sal.discovery, + org.opendaylight.controller.sal.topology, + org.opendaylight.controller.sal.routing, + org.opendaylight.controller.sal.packet, + org.opendaylight.controller.sal.packet.address, + org.opendaylight.controller.sal.utils, + org.opendaylight.controller.sal.match, + org.opendaylight.controller.sal.inventory, + org.opendaylight.controller.sal.flowprogrammer, + org.opendaylight.controller.sal.reader + + + + + + + + + junit + junit + 4.8.1 + test + + + diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Action.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Action.java new file mode 100644 index 0000000000..b4f9cb58da --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Action.java @@ -0,0 +1,138 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlTransient; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Represents the generic action to be applied to the matched frame/packet/message + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +@XmlSeeAlso({Controller.class, Drop.class, Flood.class, FloodAll.class, HwPath.class, Loopback.class, Output.class, + PopVlan.class, PushVlan.class, SetDlDst.class, SetDlSrc.class, SetDlType.class, SetNwDst.class, SetNwSrc.class, + SetNwTos.class, SetTpDst.class, SetTpSrc.class, SetVlanCfi.class, SetVlanId.class, SetVlanPcp.class, SwPath.class}) +public abstract class Action { + private static final Logger logger = LoggerFactory.getLogger(Action.class); + private static boolean debug = false; // Enable to find where in the code an invalid assignment is made + @XmlTransient + protected ActionType type; + private transient boolean isValid = true; + + /* Dummy constructor for JAXB */ + public Action () { + } + + /* + public Action (ActionType type, Object value) { + this.type = type; + this.value = value; + this.isValid = true; + } */ + + /** + * Checks if the passed value is in the valid range for this action + * + * @param value + * @return boolean + */ + protected void checkValue(int value) { + if (type.isValidTarget(value) == false) { + isValid = false; + throwValueException(value); + } + } + + /** + * Checks if the passed value is in the valid range for the passed action type + * This method is used for complex Action types which are + * + * @param value + * @return boolean + */ + protected void checkValue(ActionType type, int value) { + if (type.isValidTarget(value) == false) { + isValid = false; + throwValueException(value); + } + } + + /** + * Throw and handle the invalid value exception + * + * @param value + * @return void + */ + private void throwValueException(int value) { + String error = "Invalid field value assignement. For type: " + + type.getId() + " Expected: " + type.getRange() + ", Got: 0x" + + Integer.toHexString(value); + try { + throw new Exception(error); + } catch (Exception e) { + logger.error(e.getMessage()); + if (debug) { + e.printStackTrace(); + } + } + } + + /** + * Returns the type of this action + * + * @return ActionType + */ + public ActionType getType() { + return type; + } + + /** + * Returns the id of this action + * + * @return String + */ + public String getId() { + return type.getId(); + } + + /** + * Returns whether the Action is valid or not + * + * @return boolean + */ + public boolean isValid() { + return isValid; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return type.toString(); + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/ActionType.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/ActionType.java new file mode 100644 index 0000000000..8582046fa9 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/ActionType.java @@ -0,0 +1,73 @@ + +/* + * 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.controller.sal.action; + +/** + * The enumeration of actions supported by the controller + * Each entry has a unique id and the values range for the action element where applicable + * + * + * + */ +public enum ActionType { + DROP("drop", 0, 0), LOOPBACK("loopback", 0, 0), FLOOD("flood", 0, 0), // regular switching flood (obeys to stp port state) + FLOOD_ALL("floodAll", 0, 0), // flood to all ports regardless of stp port state + CONTROLLER("controller", 0, 0), INTERFACE("interface", 0, 0), // Interface + SW_PATH("software path", 0, 0), // OF Local + HW_PATH("harware path", 0, 0), OUTPUT("output", 0, 0xffff), // physical port + ENQUEUE("enqueue", 0, 0xffff), SET_DL_SRC("setDlSrc", 0, 0), SET_DL_DST( + "setDlDst", 0, 0), SET_VLAN_ID("setVlan", 2, 0xfff), SET_VLAN_PCP( + "setVlanPcp", 0, 0x7), SET_VLAN_CFI("setVlanCif", 0, 0x1), POP_VLAN( + "stripVlan", 0, 0), // Pop + PUSH_VLAN("pushVlan", 0, 0xffff), // Push (the max value only takes into account the TCI portion of the 802.1q header) + SET_DL_TYPE("setDlType", 0, 0xffff), // Set ethertype/length field + SET_NW_SRC("setNwSrc", 0, 0), SET_NW_DST("setNwDst", 0, 0), SET_NW_TOS( + "setNwTos", 0, 0xff), SET_TP_SRC("setTpSrc", 0, 0xffff), SET_TP_DST( + "setTpDst", 0, 0xffff), SET_NEXT_HOP("setNextHop", 0, 0); + + private String id; + private int minValue; + private int maxValue; + + private ActionType(String id, int minValue, int maxValue) { + this.id = id; + this.minValue = minValue; + this.maxValue = maxValue; + } + + public String getId() { + return id; + } + + public boolean isValidTarget(int value) { + return (value >= minValue && value <= maxValue); + } + + public String getRange() { + return "[0x" + Long.toHexString(minValue) + "-0x" + + Long.toHexString(maxValue) + "]"; + } + + public boolean takesParameter() { + switch (this) { + case POP_VLAN: + case DROP: + case SW_PATH: + case HW_PATH: + case CONTROLLER: + case LOOPBACK: + case FLOOD: + case FLOOD_ALL: + return false; + default: + return true; + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Controller.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Controller.java new file mode 100644 index 0000000000..1c7cc7b7a3 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Controller.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents the action of punting the packet to the controller + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class Controller extends Action { + + public Controller() { + type = ActionType.CONTROLLER; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Drop.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Drop.java new file mode 100644 index 0000000000..1297a15f69 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Drop.java @@ -0,0 +1,28 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represent the action of dropping the matched packet + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class Drop extends Action { + public Drop() { + type = ActionType.DROP; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Flood.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Flood.java new file mode 100644 index 0000000000..4d2436b1bf --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Flood.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents the action of flooding the packet out + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class Flood extends Action { + + public Flood() { + type = ActionType.FLOOD; + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/FloodAll.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/FloodAll.java new file mode 100644 index 0000000000..b0f60d4b92 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/FloodAll.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents the action of flooding the packet out all the physical ports except the input port + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class FloodAll extends Action { + + public FloodAll() { + type = ActionType.FLOOD_ALL; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/HwPath.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/HwPath.java new file mode 100644 index 0000000000..fc7786719d --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/HwPath.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents the action of sending the packet to the local hardware path for processing + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class HwPath extends Action { + + public HwPath() { + type = ActionType.HW_PATH; + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Loopback.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Loopback.java new file mode 100644 index 0000000000..b930eecacc --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Loopback.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents the action of looping the packet back the port it came in from + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class Loopback extends Action { + + public Loopback() { + type = ActionType.LOOPBACK; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Output.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Output.java new file mode 100644 index 0000000000..8c23da8cfa --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Output.java @@ -0,0 +1,62 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.core.NodeConnector; + +/** + * Represents the action of sending the packet out of a physical port + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class Output extends Action { + @XmlElement + private NodeConnector port; + + /* Dummy constructor for JAXB */ + private Output () { + } + + public Output(NodeConnector port) { + type = ActionType.OUTPUT; + this.port = port; + //checkValue(port); + } + + public NodeConnector getPort() { + return port; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[" + port.toString() + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PopVlan.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PopVlan.java new file mode 100644 index 0000000000..6ef37fd9fa --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PopVlan.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Pop vlan action (strip the outermost 802.1q header) + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class PopVlan extends Action { + + public PopVlan() { + type = ActionType.POP_VLAN; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PushVlan.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PushVlan.java new file mode 100644 index 0000000000..d50851ae49 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PushVlan.java @@ -0,0 +1,165 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.utils.EtherTypes; + +/** + * Insert a 802.1q (outermost) header action + * Execute it multiple times to achieve QinQ + * + * 802.1q = [TPID(16) + TCI(16)] + * TCI = [PCP(3) + CFI(1) + VID(12)] + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class PushVlan extends Action { + private int tag; // TPID - 16 bits + private int pcp; // PCP - 3 bits + private int cfi; // CFI - 1 bit (drop eligible) + private int vlanId; // VID - 12 bits + private transient int tci; // TCI = [PCP + CFI + VID] - 16 bits + private transient int header; // full 802.1q header [TPID + TCI] - 32 bits + + /* Dummy constructor for JAXB */ + private PushVlan () { + } + + public PushVlan(int tag, int pcp, int cfi, int vlanId) { + type = ActionType.PUSH_VLAN; + this.tag = tag; + this.cfi = cfi; + this.pcp = pcp; + this.vlanId = vlanId; + this.tci = createTci(); + this.header = createHeader(); + runChecks(); + } + + public PushVlan(EtherTypes tag, int pcp, int cfi, int vlanId) { + type = ActionType.PUSH_VLAN; + this.tag = tag.intValue(); + this.cfi = cfi; + this.pcp = pcp; + this.vlanId = vlanId; + this.tci = createTci(); + this.header = createHeader(); + runChecks(); + } + + private int createTci() { + return (pcp & 0x7) << 13 | (cfi & 0x1) << 12 | (vlanId & 0xfff); + } + + private int createHeader() { + return (tag & 0xffff) << 16 | (pcp & 0x7) << 13 | (cfi & 0x1) << 12 + | (vlanId & 0xfff); + } + + private void runChecks() { + checkValue(ActionType.SET_DL_TYPE, tag); + checkValue(ActionType.SET_VLAN_PCP, pcp); + checkValue(ActionType.SET_VLAN_CFI, cfi); + checkValue(ActionType.SET_VLAN_ID, vlanId); + checkValue(tci); + + // Run action specific check which cannot be run by parent + if (tag != EtherTypes.VLANTAGGED.intValue() + && tag != EtherTypes.QINQ.intValue() + && tag != EtherTypes.OLDQINQ.intValue() + && tag != EtherTypes.CISCOQINQ.intValue()) { + // pass a value which will tell fail and tell something about the original wrong value + checkValue(ActionType.SET_DL_TYPE, 0xBAD << 16 | tag); + } + } + + /** + * Returns the VID portion of the 802.1q header this action will insert + * VID - (12 bits) + * @return byte[] + */ + public int getVlanId() { + return vlanId; + } + + /** + * Returns the CFI portion of the 802.1q header this action will insert + * CFI - (1 bit) + * @return + */ + public int getCfi() { + return cfi; + } + + /** + * Returns the vlan PCP portion of the 802.1q header this action will insert + * PCP - (3 bits) + * @return byte[] + */ + public int getPcp() { + return pcp; + } + + /** + * Returns the TPID portion of the 802.1q header this action will insert + * TPID - (16 bits) + */ + public int getTag() { + return tag; + } + + /** + * Returns the TCI portion of the 802.1q header this action will insert + * TCI = [PCP + CFI + VID] - (16 bits) + * @return + */ + public int getTci() { + return tci; + } + + /** + * Returns the full 802.1q header this action will insert + * header = [TPID + TIC] (32 bits) + * + * @return int + */ + @XmlElement(name="VlanHeader") + public int getHeader() { + return header; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[tag = " + tag + ", pcp = " + pcp + ", cfi = " + cfi + + ", vlanId = " + vlanId + "]"; + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlDst.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlDst.java new file mode 100644 index 0000000000..53c2806443 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlDst.java @@ -0,0 +1,68 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.utils.HexEncode; + +/** + * Set destination datalayer address action + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetDlDst extends Action { + private byte[] address; + + /* Dummy constructor for JAXB */ + private SetDlDst () { + } + + public SetDlDst(byte[] dlAddress) { + type = ActionType.SET_DL_DST; + this.address = dlAddress.clone(); + } + + /** + * Returns the datalayer address that this action will set + * + * @return byte[] + */ + public byte[] getDlAddress() { + return address.clone(); + } + + @XmlElement(name = "address") + public String getDlAddressString() { + return HexEncode.bytesToHexString(address); + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[address = " + HexEncode.bytesToHexString(address) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlSrc.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlSrc.java new file mode 100644 index 0000000000..9d31fe274e --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlSrc.java @@ -0,0 +1,72 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.utils.HexEncode; + +/** + * Set source datalayer address action + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetDlSrc extends Action { + private byte[] address; + + /* Dummy constructor for JAXB */ + private SetDlSrc () { + } + + public SetDlSrc(byte[] dlAddress) { + type = ActionType.SET_DL_SRC; + if (dlAddress != null) { + this.address = dlAddress.clone(); + } else { + this.address = null; + } + } + + /** + * Returns the datalayer address that this action will set + * + * @return byte[] + */ + public byte[] getDlAddress() { + return address.clone(); + } + + @XmlElement(name = "address") + public String getDlAddressString() { + return HexEncode.bytesToHexString(address); + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[address = " + HexEncode.bytesToHexString(address) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlType.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlType.java new file mode 100644 index 0000000000..51a24a6ac2 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlType.java @@ -0,0 +1,71 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.utils.EtherTypes; + +/** + * Set ethertype/length field action + */ + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetDlType extends Action { + @XmlElement + private int dlType; + + /* Dummy constructor for JAXB */ + private SetDlType () { + } + + public SetDlType(int dlType) { + type = ActionType.SET_DL_TYPE; + this.dlType = dlType; + checkValue(dlType); + } + + public SetDlType(EtherTypes dlType) { + type = ActionType.SET_DL_TYPE; + this.dlType = dlType.intValue(); + checkValue(this.dlType); + } + + /** + * Returns the ethertype/lenght value that this action will set + * + * @return byte[] + */ + public int getDlType() { + return dlType; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[dlType = 0x" + Integer.toHexString(dlType) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwDst.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwDst.java new file mode 100644 index 0000000000..7db7081ab9 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwDst.java @@ -0,0 +1,69 @@ + +/* + * 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.controller.sal.action; + +import java.net.InetAddress; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Set network destination address action + */ + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetNwDst extends Action { + InetAddress address; + + /* Dummy constructor for JAXB */ + private SetNwDst () { + } + + public SetNwDst(InetAddress address) { + type = ActionType.SET_NW_DST; + this.address = address; + } + + /** + * Returns the network address this action will set + * + * @return InetAddress + */ + public InetAddress getAddress() { + return address; + } + + @XmlElement (name="address") + public String getAddressAsString() { + return address.getHostAddress(); + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[address = " + address + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwSrc.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwSrc.java new file mode 100644 index 0000000000..3e75e47502 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwSrc.java @@ -0,0 +1,69 @@ + +/* + * 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.controller.sal.action; + +import java.net.InetAddress; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Set network source address action + */ + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetNwSrc extends Action { + InetAddress address; + + /* Dummy constructor for JAXB */ + private SetNwSrc () { + } + + public SetNwSrc(InetAddress address) { + type = ActionType.SET_NW_SRC; + this.address = address; + } + + /** + * Returns the network address this action will set + * + * @return InetAddress + */ + public InetAddress getAddress() { + return address; + } + + @XmlElement (name="address") + public String getAddressAsString() { + return address.getHostAddress(); + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[address = " + address + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwTos.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwTos.java new file mode 100644 index 0000000000..33c96d3738 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwTos.java @@ -0,0 +1,63 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Set network TOS action + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetNwTos extends Action { + @XmlElement + private int tos; + + /* Dummy constructor for JAXB */ + private SetNwTos () { + } + + public SetNwTos(int tos) { + type = ActionType.SET_NW_TOS; + this.tos = tos; + checkValue(tos); + } + + /** + * Returns the network TOS value which the action will set + * + * @return int + */ + public int getNwTos() { + return tos; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[tos = 0x" + Integer.toHexString(tos) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpDst.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpDst.java new file mode 100644 index 0000000000..fb7c824494 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpDst.java @@ -0,0 +1,62 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Set destination transport port action + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetTpDst extends Action { + @XmlElement + private int port; + + /* Dummy constructor for JAXB */ + private SetTpDst () { + } + + public SetTpDst(int port) { + type = ActionType.SET_TP_DST; + this.port = port; + checkValue(port); + } + + /** + * Returns the transport port the action will set + * @return + */ + public int getPort() { + return port; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[port = " + port + "]"; + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpSrc.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpSrc.java new file mode 100644 index 0000000000..20210ad5e8 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpSrc.java @@ -0,0 +1,63 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Set source transport port action + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetTpSrc extends Action { + @XmlElement + private int port; + + /* Dummy constructor for JAXB */ + private SetTpSrc () { + } + + public SetTpSrc(int port) { + type = ActionType.SET_TP_SRC; + this.port = port; + checkValue(port); + } + + /** + * Returns the transport port the action will set + * @return + */ + public int getPort() { + return port; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[port = " + port + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanCfi.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanCfi.java new file mode 100644 index 0000000000..c21430e9e9 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanCfi.java @@ -0,0 +1,63 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Set vlan CFI action + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetVlanCfi extends Action { + @XmlElement + private int cfi; + + /* Dummy constructor for JAXB */ + private SetVlanCfi () { + } + + public SetVlanCfi(int cfi) { + type = ActionType.SET_VLAN_CFI; + this.cfi = cfi; + checkValue(cfi); + } + + /** + * Returns the 802.1q CFI value that this action will set + * @return + */ + public int getCfi() { + return cfi; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[cfi = " + Integer.toHexString(cfi) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanId.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanId.java new file mode 100644 index 0000000000..9c9b364b89 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanId.java @@ -0,0 +1,64 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Set vlan id action + */ + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetVlanId extends Action { + @XmlElement + private int vlanId; + + private SetVlanId() { + + } + + public SetVlanId(int vlanId) { + type = ActionType.SET_VLAN_ID; + this.vlanId = vlanId; + checkValue(vlanId); + } + + /** + * Returns the vlan id this action will set + * + * @return int + */ + public int getVlanId() { + return vlanId; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[vlanId = " + vlanId + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanPcp.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanPcp.java new file mode 100644 index 0000000000..5c315debff --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanPcp.java @@ -0,0 +1,62 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Set vlan PCP action + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SetVlanPcp extends Action { + @XmlElement + private int pcp; + + private SetVlanPcp() { + + } + + public SetVlanPcp(int pcp) { + type = ActionType.SET_VLAN_PCP; + this.pcp = pcp; + checkValue(pcp); + } + + /** + * Returns the value of the vlan PCP this action will set + * @return int + */ + public int getPcp() { + return pcp; + } + + @Override + public boolean equals(Object other) { + return EqualsBuilder.reflectionEquals(this, other); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return type + "[pcp = " + Integer.toHexString(pcp) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SwPath.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SwPath.java new file mode 100644 index 0000000000..f30d2ee743 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SwPath.java @@ -0,0 +1,27 @@ + +/* + * 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.controller.sal.action; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Represents the action of sending the packet to the local software path for processing + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class SwPath extends Action { + + public SwPath() { + type = ActionType.SW_PATH; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRole.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRole.java new file mode 100644 index 0000000000..ae867c56d3 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRole.java @@ -0,0 +1,44 @@ + +/* + * 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.controller.sal.authorization; + +import java.io.Serializable; + +/** + * Represents a user role level in the application space + * It contains the role name and the role level in the + * application context as specified by {@link AppRoleLevel} + */ +public class AppRole implements Serializable { + private static final long serialVersionUID = 1L; + String name; + AppRoleLevel level; + + public AppRole(String name, AppRoleLevel level) { + this.name = name; + this.level = level; + } + + /** + * Returns the application role name + * @return the string containing the role name + */ + public String getName() { + return name; + } + + /** + * Returns the application role level + * @return the application user level + */ + public AppRoleLevel getLevel() { + return level; + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRoleLevel.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRoleLevel.java new file mode 100644 index 0000000000..aa6514cd74 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AppRoleLevel.java @@ -0,0 +1,46 @@ + +/* + * 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.controller.sal.authorization; + +import java.io.Serializable; + +/** + * Represents the application user role levels + * This level has meaning only inside the application context + * In the controller space such a role will be seen as APPUSER + * as specified in {@link UserLevel} + */ +public enum AppRoleLevel implements Serializable { + APPADMIN(0, "App-Admin", "Application Administrator"), APPUSER(1, + "App-User", "Application User"), APPOPERATOR(2, "Network-Operator", + "Application Operator"), NOUSER(255, "Unknown User", "Unknown User"); + + private int userLevel; + private String level; + private String prettyLevel; + + private AppRoleLevel(int userlevel, String level, String prettyLevel) { + this.userLevel = userlevel; + this.level = level; + this.prettyLevel = prettyLevel; + } + + public int toNumber() { + return this.userLevel; + } + + public String toString() { + return this.level; + } + + public String toStringPretty() { + return this.prettyLevel; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AuthResultEnum.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AuthResultEnum.java new file mode 100644 index 0000000000..cbcc2029cd --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/AuthResultEnum.java @@ -0,0 +1,52 @@ + +/* + * 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 + */ + +/** + * Defines the enumerated values for possible results of an Authentication + * request made from a AAA client to a AAA server. + */ + +package org.opendaylight.controller.sal.authorization; + +import java.io.Serializable; + +public enum AuthResultEnum implements Serializable { + AUTH_NONE("AUTH_NOT_ATTEMPTED"), AUTH_ACCEPT("AUTHENTICATION_ACCEPTED"), // request accepted + AUTH_REJECT("AUTHENTICATION_REJECTED"), // request rejected + AUTH_TIMEOUT("AUTHENTICATION_TIMEDOUT"), // request timeout + AUTH_USERNAME_EMPTY("AUTHENTICATION_USERNAME_EMPTY"), // user name is empty + AUTH_PASSWORD_EMPTY("AUTHENTICATION_PASSWORD_EMPTY"), // password is empty + AUTH_SECRET_EMPTY("AUTHENTICATION_SECRET_EMPTY"), // secret is empty + AUTH_COMM_ERROR("AUTHENTICATION_COMM_ERROR"), // communication channel problem + AUTH_INVALID_ADDR("AUTHENTICATION_INVALID_ADDR"), // invalid network address + AUTH_INVALID_PACKET("AUTHENTICATION_INVALID_PACKET"), // invalid packets or malformed attributes + + /* + * Local AAA values + */ + AUTH_ACCEPT_LOC("AUTHENTICATION_ACCEPTED"), // request accepted on local database + AUTH_REJECT_LOC("AUTHENTICATION_REJECTED"), // request rejected on local database + AUTH_INVALID_LOC_USER("INALID_LOCAL_USER"), + + /* + * Authorization + */ + AUTHOR_PASS("AUTHORIZATION_PASSED"), AUTHOR_FAIL("AUTHORIZATION_FAILED"), AUTHOR_ERROR( + "AUTHORIZATION_SERVER_ERROR"); + + private AuthResultEnum(String name) { + this.name = name; + } + + private String name; + + public String toString() { + return name; + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/IResourceAuthorization.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/IResourceAuthorization.java new file mode 100644 index 0000000000..1609674824 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/IResourceAuthorization.java @@ -0,0 +1,153 @@ + +/* + * 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.controller.sal.authorization; + +import java.util.List; +import java.util.Set; + +/** + * Interface for applications which maintain an authorization + * database for their resources. Respective application web bundle + * and User Manager make use of this interface to retrieve + * authorization information at user or and role level + */ +public interface IResourceAuthorization { + + /** + * Create a Role name for the application + * + * @param role the role name + * @param userLevel the user level in the application context + */ + public void createRole(String role, AppRoleLevel userLevel); + + /** + * Return the list of roles configured for the application + * + * @return the list of roles + */ + public List getRoles(); + + /** + * Returns the application role level for the specified role + * If the role is not known to this application NOUSER + * will be returned as specified in {@link AppRoleLevel} + * + * @param roleName the role name to query + * @return the application level of the given role in the application context as specified by {@link AppRoleLevel} + * if the role is not part of this application's roles, NOUSER is returned + */ + public AppRoleLevel getApplicationRoleLevel(String roleName); + + /** + * Returns whether the specified role is part of this application's roles + * + * @param roleName the role name to test + * @return true if the role belongs to this application, false otherwise + */ + public boolean isApplicationRole(String roleName); + + /** + * Create a resource group for application + * + * @param groupName the name for the resource group + * @param resources the list of resources for the group + */ + public void createResourceGroup(String groupName, List resources); + + /** + * Removes a resource group + * + * @param groupName the name of the group + */ + public void removeResourceGroup(String groupName); + + /** + * Returns the list of resource groups configured for the application + * + * @return the list of resource group names + */ + public List getResourceGroups(); + + /** + * Assign a resource group to a user group (role) + * + * @param groupName the object expressing the resource group name and the access privilege + * @param role the user group (role) name + */ + public void assignResourceGroupToRole(String groupName, + Privilege privilege, String role); + + /** + * Returns the list of resource groups the given Role is authorized to use + * The returning object expresses the resource group name and the access + * its privilege for the given user role + * + * @param role + * @return list of resources + */ + public List getAuthorizedGroups(String role); + + /** + * Returns the list of resources contained in the given resource group + * + * @param groupName the resource group name + * @return + */ + public List getResources(String groupName); + + /** + * Returns the list of authorized resources for the given role + * For each resource only the highest privilege occurrence is returned + * @param role + * @return the list of Resource + */ + public List getAuthorizedResources(String role); + + /* + * Per user name API + */ + /** + * Returns the controller user role level the passed user name is associated with + * + * @param userName the user name + * @return the user role level as specified in {@link UserLevel} + */ + public UserLevel getUserLevel(String userName); + + /** + * Returns the application context user role level the passed user name is associated with + * + * @param userName the user name + * @return the user role level as specified in {@link AppRoleLevel} + */ + public AppRoleLevel getUserApplicationLevel(String userName); + + /** + * Returns the list of resources (resource + privilege) associated + * with the passed user name for this application context + * For each resource only the highest privilege occurrence is returned + * + * @param userName the user name + * @return the list of resources associated with this user name in this application context + */ + public Set getAllResourcesforUser(String userName); + + /** + * Returns the highest privilege that the user has on the specified + * resource in this application context + * + * @param userName + * @param resource + * @return + */ + public Privilege getResourcePrivilege(String userName, Object resource); + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/Privilege.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/Privilege.java new file mode 100644 index 0000000000..63babe7d0a --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/Privilege.java @@ -0,0 +1,32 @@ + +/* + * 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.controller.sal.authorization; + +/** + * It represents the group/resource access privilege + */ +public enum Privilege { + NONE(""), // no privilege + READ("r"), // read only + USE("u"), // use + WRITE("w"); // modify + + private String p; + + private Privilege(String p) { + this.p = p; + } + + @Override + public String toString() { + return p; + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/Resource.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/Resource.java new file mode 100644 index 0000000000..ef8744b551 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/Resource.java @@ -0,0 +1,53 @@ + +/* + * 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.controller.sal.authorization; + +import java.io.Serializable; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * It represents the elementary resource along with + * the access privilege associated to it + */ +public class Resource implements Serializable { + private static final long serialVersionUID = 1L; + Object resource; // the generic resource + Privilege privilege; // read/use/write privilege + + public Resource(Object resource, Privilege privilege) { + this.resource = resource; + this.privilege = privilege; + } + + public Object getResource() { + return resource; + } + + public Privilege getPrivilege() { + return privilege; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "[" + resource + ", " + privilege.toString() + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/ResourceGroup.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/ResourceGroup.java new file mode 100644 index 0000000000..61e44dda4b --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/ResourceGroup.java @@ -0,0 +1,63 @@ + +/* + * 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.controller.sal.authorization; + +import java.io.Serializable; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * Represents a group of resources along with the privilege associated to it + * + * + * + */ +public class ResourceGroup implements Serializable { + private static final long serialVersionUID = 1L; + private String groupName; // the resource group name + private Privilege privilege; // the privilege for this profile on the resource group + + public ResourceGroup(String groupName, Privilege privilege) { + this.groupName = groupName; + this.privilege = privilege; + } + + /** + * Returns the name for this resource group + * @return + */ + public String getGroupName() { + return groupName; + } + + /** + * Returns the privilege for this group on its resources + * @return + */ + public Privilege getPrivilege() { + return privilege; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "[" + groupName + ", " + privilege.toString() + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/UserLevel.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/UserLevel.java new file mode 100644 index 0000000000..a2e1d1c56d --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/authorization/UserLevel.java @@ -0,0 +1,46 @@ + +/* + * 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.controller.sal.authorization; + +import java.io.Serializable; + +/** + * Describes the user role level in the controller space + */ +public enum UserLevel implements Serializable { + SYSTEMADMIN(0, "System-Admin", "System Administrator"), // can do everything + NETWORKADMIN(1, "Network-Admin", "Network Administrator"), // can do everything but setting a system admin user profile + NETWORKOPERATOR(2, "Network-Operator", "Network Operator"), // can only see what is configured anywhere + CONTAINERUSER(4, "Container-User", "Container User"), // container context user + APPUSER(5, "App-User", "Application User"), // application context user + NOUSER(255, "Not Authorized", "Not Authorized"); + + private int userLevel; + private String level; + private String prettyLevel; + + private UserLevel(int userlevel, String level, String prettyLevel) { + this.userLevel = userlevel; + this.level = level; + this.prettyLevel = prettyLevel; + } + + public int toNumber() { + return this.userLevel; + } + + public String toString() { + return this.level; + } + + public String toStringPretty() { + return this.prettyLevel; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java new file mode 100644 index 0000000000..832c9565a5 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java @@ -0,0 +1,99 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * @file Actions.java + * + * @brief Class representing actions + * + * Describes supported actions + */ + +@XmlRootElement +public class Actions extends Property { + private static final long serialVersionUID = 1L; + @XmlElement + private int actionsValue; + + public enum ActionType { + OUTPUT_PORT_ACTION(1<<0), + VLAN_VID_ACTION(1<<1), + VLAN_PCP_ACTION(1<<2), + VLAN_STRIP_ACTION(1<<3), + DLSRC_ACTION(1<<4), + DLDST_ACTION(1<<5), + NWSRC_ACTION(1<<6), + NWDST_ACTION(1<<7), + NWTOS_ACTION(1<<8), + TPTSRC_ACTION(1<<9), + TPTDST_ACTION(1<<10), + ENQUEUE_ACTION(1<<11), + VENDOR_ACTION(0xffff); + private final int at; + ActionType(int val) { + this.at = val; + } + public int getValue() { + return at; + } + } + + public static final String ActionsPropName = "actions"; + /** + * Construct a actions property + * + * @param actions the actions value + * @return Constructed object + */ + public Actions(int actions) { + super(ActionsPropName); + this.actionsValue = actions; + } + + /* + * Private constructor used for JAXB mapping + */ + private Actions() { + super(ActionsPropName); + this.actionsValue = 0; + } + + public Actions clone() { + return new Actions(this.actionsValue); + } + + public int getValue() { + return this.actionsValue; + } + + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Actions[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/AdvertisedBandwidth.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/AdvertisedBandwidth.java new file mode 100644 index 0000000000..b07dc34806 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/AdvertisedBandwidth.java @@ -0,0 +1,67 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * @file AdvertisedBandWidth.java + * + * @brief Class representing advertised bandwidth + * + * Describes Advertised Bandwidth which could be of a link or whatever could have + * bandwidth as description. It's intended in multiple of bits per + * seconds. + */ +@XmlRootElement +@SuppressWarnings("serial") +public class AdvertisedBandwidth extends Bandwidth { + public static final String AdvertisedBandwidthPropName = "advertisedBandwidth"; + + public AdvertisedBandwidth(long value) { + super(AdvertisedBandwidthPropName); + this.bandwidthValue = value; + } + + /* + * Private constructor used for JAXB mapping + */ + private AdvertisedBandwidth() { + super(AdvertisedBandwidthPropName); + this.bandwidthValue = 0; + } + + public AdvertisedBandwidth clone() { + return new AdvertisedBandwidth(this.bandwidthValue); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("AdvertisedBandWidth["); + sb.append(super.toString()); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Bandwidth.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Bandwidth.java new file mode 100644 index 0000000000..32f661ca5f --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Bandwidth.java @@ -0,0 +1,117 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * @file BandWidth.java + * + * @brief Class representing bandwidth + * + * Describe Bandwidth which could be of a link or whatever could have + * bandwidth as description. It's intended in multiple of bits per + * seconds. + */ +@XmlRootElement +public class Bandwidth extends Property { + private static final long serialVersionUID = 1L; + + @XmlElement + protected long bandwidthValue; + + public static final long BWUNK = 0; + public static final long BW1Kbps = (long) Math.pow(10, 3); + public static final long BW1Mbps = (long) Math.pow(10, 6); + public static final long BW10Mbps = (long) Math.pow(10, 7); + public static final long BW100Mbps = (long) Math.pow(10, 8); + public static final long BW1Gbps = (long) Math.pow(10, 9); + public static final long BW10Gbps = (long) Math.pow(10, 10); + public static final long BW40Gbps = 4 * (long) Math.pow(10, 10); + public static final long BW100Gbps = (long) Math.pow(10, 11); + public static final long BW400Gbps = 4 * (long) Math.pow(10, 11); + public static final long BW1Tbps = (long) Math.pow(10, 12); + public static final long BW1Pbps = (long) Math.pow(10, 15); + + public static final String BandwidthPropName = "bandwidth"; + + /* + * Private constructor used for JAXB mapping + */ + private Bandwidth() { + super(BandwidthPropName); + this.bandwidthValue = BWUNK; + ; + } + + public Bandwidth(long bandwidth) { + super(BandwidthPropName); + this.bandwidthValue = bandwidth; + } + + public Bandwidth(int bandwidth) { + super(BandwidthPropName); + this.bandwidthValue = (long) bandwidth; + } + + public Bandwidth(short bandwidth) { + super(BandwidthPropName); + this.bandwidthValue = (long) bandwidth; + } + + public Bandwidth(String name) { + super(name); + } + + public Bandwidth clone() { + return new Bandwidth(this.bandwidthValue); + } + + public long getValue() { + return this.bandwidthValue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + + sb.append("BandWidth["); + if (this.bandwidthValue == 0) { + sb.append("UnKnown"); + } else if (this.bandwidthValue < BW1Kbps) { + sb.append(this.bandwidthValue + "bps"); + } else if (this.bandwidthValue < BW1Mbps) { + sb.append(Long.toString(this.bandwidthValue / BW1Kbps) + "Kbps"); + } else if (this.bandwidthValue < BW1Gbps) { + sb.append(Long.toString(this.bandwidthValue / BW1Mbps) + "Mbps"); + } else if (this.bandwidthValue < BW1Tbps) { + sb.append(Long.toString(this.bandwidthValue / BW1Gbps) + "Gbps"); + } else if (this.bandwidthValue < BW1Pbps) { + sb.append(Long.toString(this.bandwidthValue / BW1Tbps) + "Tbps"); + } + + sb.append("]"); + return sb.toString(); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Buffers.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Buffers.java new file mode 100644 index 0000000000..9324806ada --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Buffers.java @@ -0,0 +1,75 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * @file Buffers.java + * + * @brief Class representing buffers + * + * Describes supported buffers (#packets) + */ +@XmlRootElement +public class Buffers extends Property { + private static final long serialVersionUID = 1L; + @XmlElement + private int buffersValue; + + public static final String BuffersPropName = "buffers"; + + /** + * Construct a Buffers property + * + * @param buffers the Buffers + * @return Constructed object + */ + public Buffers(int buffers) { + super(BuffersPropName); + this.buffersValue = buffers; + } + + /* + * Private constructor used for JAXB mapping + */ + private Buffers() { + super(BuffersPropName); + this.buffersValue = 0; + } + + public Buffers clone() { + return new Buffers(this.buffersValue); + } + + public int getValue() { + return this.buffersValue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Buffers[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Capabilities.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Capabilities.java new file mode 100644 index 0000000000..b239ed4739 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Capabilities.java @@ -0,0 +1,92 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * @file Capabilities.java + * + * @brief Class representing capabilities + * + * Describes supported capabilities + */ +@XmlRootElement +public class Capabilities extends Property { + private static final long serialVersionUID = 1L; + @XmlElement + private int capabilitiesValue; + + public enum CapabilitiesType { + FLOW_STATS_CAPABILITY(1<<0), + TABLE_STATS_CAPABILITY(1<<1), + PORT_STATS_CAPABILITY(1<<2), + STP_CAPABILITY(1<<3), + RSVD_CAPABILITY(1<<4), + IP_REASSEM_CAPABILITY(1<<5), + QUEUE_STATS_CAPABILITY(1<<6), + ARP_MATCH_IP_CAPABILITY(1<<7); + private final int ct; + CapabilitiesType(int val) { + this.ct = val; + } + public int getValue() { + return ct; + } + } + + public static final String CapabilitiesPropName = "capabilities"; + /** + * Construct a Capabilities property + * + * @param capabilities the Capabilities value + * @return Constructed object + */ + public Capabilities(int capabilities) { + super(CapabilitiesPropName); + this.capabilitiesValue = capabilities; + } + + /* + * Private constructor used for JAXB mapping + */ + private Capabilities() { + super(CapabilitiesPropName); + this.capabilitiesValue = 0; + } + + public Capabilities clone() { + return new Capabilities(this.capabilitiesValue); + } + + public int getValue() { + return this.capabilitiesValue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Capabilities[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ComponentActivatorAbstractBase.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ComponentActivatorAbstractBase.java new file mode 100644 index 0000000000..d04e67b304 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ComponentActivatorAbstractBase.java @@ -0,0 +1,464 @@ + +/* + * 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.controller.sal.core; + +/** + * @file ComponentActivatorAbstractBase.java + * + * @brief Abstract class which need to be subclassed in order to + * track and register dependencies per-container + * + * Abstract class which need to be subclassed in order to + * track and register dependencies per-container + * + */ + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.felix.dm.Component; +import org.apache.felix.dm.ComponentStateListener; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.ServiceDependency; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract class which need to be subclassed in order to track and + * register dependencies per-container + * + */ +abstract public class ComponentActivatorAbstractBase implements + BundleActivator, IContainerAware { + Logger logger = LoggerFactory + .getLogger(ComponentActivatorAbstractBase.class); + private ServiceRegistration containerAwareRegistration; + private DependencyManager dm; + private ConcurrentMap, Component> dbInstances = (ConcurrentMap, Component>) new ConcurrentHashMap, Component>(); + private ConcurrentMap dbGlobalInstances = (ConcurrentMap) new ConcurrentHashMap(); + + /** + * Abstract method that MUST be implemented by the derived class + * that wants to activate the Component bundle in a container. Here + * customization for the component are expected + */ + abstract protected void init(); + + /** + * Abstract method that MUST be implemented by the derived class + * that wants to DE-activate the Component bundle in a container. Here + * customization for the component are expected + */ + abstract protected void destroy(); + + /** + * Method which tells how many implementations are supported by + * the bundle. This way we can tune the number of components + * created. + * + * + * @return The list of implementations the bundle will support, + * this will be used to decide how many components need to be + * created per-container + */ + protected Object[] getImplementations() { + return null; + } + + /** + * Method which tells how many Global implementations are + * supported by the bundle. This way we can tune the number of + * components created. This components will be created ONLY at the + * time of bundle startup and will be destroyed only at time of + * bundle destruction, this is the major difference with the + * implementation retrieved via getImplementations where all of + * them are assumed to be in a container! + * + * + * @return The list of implementations the bundle will support, + * in Global version + */ + protected Object[] getGlobalImplementations() { + return null; + } + + /** + * Configure the dependency for a given instance inside a container + * + * @param c Component assigned for this instance, this will be + * what will be used for configuration + * @param imp implementation to be configured + * @param containerName container on which the configuration happens + */ + protected void configureInstance(Component c, Object imp, + String containerName) { + // do nothing by default + } + + /** + * Configure the dependency for a given instance Global + * + * @param c Component assigned for this instance, this will be + * what will be used for configuration + * @param imp implementation to be configured + * @param containerName container on which the configuration happens + */ + protected void configureGlobalInstance(Component c, Object imp) { + // Do nothing by default + } + + // Private class used to listen to state transition so we can + // implement the necessary logic to call "started" and "stopping" + // methods on the component. Right now the framework natively + // support only the call of: + // - "init": Called after dependency are satisfied + // - "start": Called after init but before services are registered + // - "stop": Called after services are unregistered but before the + // component is going to be destroyed + // - "destroy": Called to destroy the component. + // There is still a need for two notifications: + // - "started" method to be called after "start" and after the + // services has been registered in the OSGi service registry + // - "stopping" method to be called before "stop" method and + // before the services of the component are removed from OSGi + // service registry + class ListenerComponentStates implements ComponentStateListener { + @Override + public void starting(Component component) { + // do nothing + } + + @Override + public void started(Component component) { + if (component == null) { + return; + } + component.invokeCallbackMethod(new Object[] { component + .getService() }, "started", new Class[][] { + { Component.class }, {} }, new Object[][] { { component }, + {} }); + } + + @Override + public void stopped(Component component) { + if (component == null) { + return; + } + component.invokeCallbackMethod(new Object[] { component + .getService() }, "stopping", new Class[][] { + { Component.class }, {} }, new Object[][] { { component }, + {} }); + } + + @Override + public void stopping(Component component) { + // do nothing + } + } + + /** + * Method of IContainerAware called when a new container is available + * + * @param containerName Container being created + */ + @Override + public void containerCreate(String containerName) { + try { + Object[] imps = getImplementations(); + logger.trace("Creating instance " + containerName); + if (imps != null) { + for (int i = 0; i < imps.length; i++) { + ImmutablePair key = new ImmutablePair( + containerName, imps[i]); + Component c = this.dbInstances.get(key); + if (c == null) { + c = this.dm.createComponent(); + c.addStateListener(new ListenerComponentStates()); + // Now let the derived class to configure the + // dependencies it wants + configureInstance(c, imps[i], containerName); + // Set the implementation so the component can manage + // its lifecycle + if (c.getService() == null) { + logger + .trace("Setting implementation to:" + + imps[i]); + c.setImplementation(imps[i]); + } + + //Set the service properties to include the containerName + //in the service, that is fundamental for supporting + //multiple services just distinguished via a container + Dictionary serviceProps = c + .getServiceProperties(); + if (serviceProps != null) { + logger.trace("Adding new property for container"); + serviceProps.put("containerName", containerName); + } else { + logger + .trace("Create a new properties for the service"); + serviceProps = new Hashtable(); + serviceProps.put("containerName", containerName); + } + c.setServiceProperties(serviceProps); + + // Now add the component to the dependency Manager + // which will immediately start tracking the dependencies + this.dm.add(c); + + //Now lets keep track in our shadow database of the + //association + this.dbInstances.put(key, c); + } else { + logger + .error("I have been asked again to create an instance " + + "on: " + + containerName + + "for object: " + + imps[i] + + "when i already have it!!"); + } + } + } + } catch (Exception ex) { + logger + .error("During containerDestroy invocation caught exception: " + + ex + + "\nStacktrace:" + + stackToString(ex.getStackTrace())); + } + } + + @Override + public void containerDestroy(String containerName) { + try { + Object[] imps = getImplementations(); + logger.trace("Destroying instance " + containerName); + if (imps != null) { + for (int i = 0; i < imps.length; i++) { + ImmutablePair key = new ImmutablePair( + containerName, imps[i]); + Component c = this.dbInstances.get(key); + if (c != null) { + // Now remove the component from dependency manager, + // which will implicitely stop it first + this.dm.remove(c); + } else { + logger + .error("I have been asked again to remove an instance " + + "on: " + + containerName + + "for object: " + + imps[i] + + "when i already have cleared it!!"); + } + + //Now lets remove the association from our shadow + //database so the component can be recycled, this is done + //unconditionally in case of spurious conditions + this.dbInstances.remove(key); + } + } + } catch (Exception ex) { + logger + .error("During containerDestroy invocation caught exception: " + + ex + + "\nStacktrace:" + + stackToString(ex.getStackTrace())); + } + } + + private String stackToString(StackTraceElement[] stack) { + if (stack == null) { + return ""; + } + StringBuffer buffer = new StringBuffer(); + + for (int i = 0; i < stack.length; i++) { + buffer.append("\n\t" + stack[i].toString()); + } + return buffer.toString(); + } + + /** + * Method called by the OSGi framework when the OSGi bundle + * starts. The functionality we want to perform here are: + * + * 1) Register with the OSGi framework, that we are a provider of + * IContainerAware service and so in case of startup of a container we + * want to be called + * + * 2) Create data structures that allow to keep track of all the + * instances created per-container given the derived class of + * ComponentActivatorAbstractBase will act as a Factory manager + * + * @param context OSGi bundle context to interact with OSGi framework + */ + @Override + public void start(BundleContext context) { + try { + this.dm = new DependencyManager(context); + + logger.trace("Activating"); + + // Now create Global components + Object[] imps = getGlobalImplementations(); + if (imps != null) { + for (int i = 0; i < imps.length; i++) { + Object key = imps[i]; + Component c = this.dbGlobalInstances.get(key); + if (c == null) { + try { + c = this.dm.createComponent(); + c.addStateListener(new ListenerComponentStates()); + // Now let the derived class to configure the + // dependencies it wants + configureGlobalInstance(c, imps[i]); + // Set the implementation so the component + // can manage its lifesycle + if (c.getService() == null) { + logger.trace("Setting implementation to:" + + imps[i]); + c.setImplementation(imps[i]); + } + + // Now add the component to the dependency + // Manager which will immediately start + // tracking the dependencies + this.dm.add(c); + } catch (Exception nex) { + logger.error("During creation of a Global " + + "instance caught exception: " + nex + + "\nStacktrace:" + + stackToString(nex.getStackTrace())); + } + + //Now lets keep track in our shadow database of the + //association + if (c != null) + this.dbGlobalInstances.put(key, c); + } else { + logger.error("I have been asked again to create an " + + "instance " + " Global for object: " + + imps[i] + "when i already have it!!"); + } + } + } + + // Register with OSGi the provider for the service IContainerAware + this.containerAwareRegistration = context.registerService( + IContainerAware.class.getName(), this, null); + + // Now call the derived class init function + this.init(); + + logger.trace("Activation DONE!"); + } catch (Exception ex) { + logger.error("During Activator start caught exception: " + ex + + "\nStacktrace:" + stackToString(ex.getStackTrace())); + } + } + + /** + * Method called by the OSGi framework when the OSGi bundle + * stops. The functionality we want to perform here are: + * + * 1) Force all the instances to stop and do cleanup and + * unreference them so garbage collection can clean them up + * + * NOTE: UN-Register with the OSGi framework,is not needed because + * the framework will automatically do it + * + * @param context OSGi bundle context to interact with OSGi framework + */ + @Override + public void stop(BundleContext context) { + try { + logger.trace("DE-Activating"); + + // Now call the derived class destroy function + this.destroy(); + + // Now remove all the components tracked for container components + for (ImmutablePair key : this.dbInstances.keySet()) { + try { + Component c = this.dbInstances.get(key); + if (c != null) { + logger.trace("Remove component on container:" + + key.getLeft() + " Object:" + key.getRight()); + this.dm.remove(c); + } + } catch (Exception nex) { + logger.error("During removal of a container component " + + "instance caught exception: " + nex + + "\nStacktrace:" + + stackToString(nex.getStackTrace())); + } + this.dbInstances.remove(key); + } + + // Now remove all the components tracked for Global Components + for (Object key : this.dbGlobalInstances.keySet()) { + try { + Component c = this.dbGlobalInstances.get(key); + if (c != null) { + logger.trace("Remove component for Object:" + key); + this.dm.remove(c); + } + } catch (Exception nex) { + logger.error("During removal of a Global " + + "instance caught exception: " + nex + + "\nStacktrace:" + + stackToString(nex.getStackTrace())); + } + + this.dbGlobalInstances.remove(key); + } + + // Detach Dependency Manager + this.dm = null; + + logger.trace("Deactivation DONE!"); + } catch (Exception ex) { + logger.error("During Activator stop caught exception: " + ex + + "\nStacktrace:" + stackToString(ex.getStackTrace())); + } + } + + /** + * Return a ServiceDependency customized ad hoc for slicing, this + * essentially the same org.apache.felix.dm.ServiceDependency just + * with some filters pre-set + * + * @param containerName containerName for which we want to create the dependency + * + * @return a ServiceDependency + */ + protected ServiceDependency createContainerServiceDependency( + String containerName) { + return (new ContainerServiceDependency(this.dm, containerName)); + } + + /** + * Return a ServiceDependency as provided by Dependency Manager as it's + * + * + * @return a ServiceDependency + */ + protected ServiceDependency createServiceDependency() { + return this.dm.createServiceDependency(); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Config.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Config.java new file mode 100644 index 0000000000..c585aa2c9f --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Config.java @@ -0,0 +1,70 @@ + +/* + * 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.controller.sal.core; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlElement; + +/** + * The class represents Admin Config status + * + * + */ +@XmlRootElement +@SuppressWarnings("serial") +public class Config extends Property { + @XmlElement + private short configValue; + + public static final short ADMIN_DOWN = 0; + public static final short ADMIN_UP = 1; + public static final short ADMIN_UNDEF = 0x7fff; + public static final String ConfigPropName = "config"; + + /* + * Private constructor used for JAXB mapping + */ + private Config() { + super(ConfigPropName); + this.configValue = ADMIN_UNDEF; + } + + public Config(short config) { + super(ConfigPropName); + this.configValue = config; + } + + public Config clone() { + return new Config(this.configValue); + } + + public short getValue() { + return this.configValue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Config[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ConstructionException.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ConstructionException.java new file mode 100644 index 0000000000..30033a244c --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ConstructionException.java @@ -0,0 +1,30 @@ + +/* + * 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 + */ + +/** + * @file ConstructionException.java + * + * + * @brief Describe an exception that is raised when a construction + * for a Node/NodeConnector/Edge or any of the SAL basic object fails + * because input passed are not valid or compatible + * + * + */ +package org.opendaylight.controller.sal.core; + +import java.lang.Exception; + +public class ConstructionException extends Exception { + private static final long serialVersionUID = 1L; + + public ConstructionException(String message) { + super(message); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ContainerFlow.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ContainerFlow.java new file mode 100644 index 0000000000..acb3e19f69 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ContainerFlow.java @@ -0,0 +1,123 @@ + +/* + * 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.controller.sal.core; + +import java.io.Serializable; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.action.Action; +import org.opendaylight.controller.sal.action.SetDlType; +import org.opendaylight.controller.sal.action.SetNwDst; +import org.opendaylight.controller.sal.action.SetNwSrc; +import org.opendaylight.controller.sal.action.SetTpDst; +import org.opendaylight.controller.sal.action.SetTpSrc; +import org.opendaylight.controller.sal.flowprogrammer.Flow; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; + +/** + * Express a container flow + * + * + * + */ +public class ContainerFlow implements Serializable { + private static final long serialVersionUID = 1L; + private Match match; + + public ContainerFlow(Match match) { + this.match = match; + } + + /** + * Returns a copy of the Match defined by this Container Flow + * + * @return Match + */ + public Match getMatch() { + return match.clone(); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Container Flow [" + match.toString() + "]"; + } + + /** + * Returns whether the specified flow is allowed + * + * @return true if the flow is allowed, false otherwise + */ + public boolean allowsFlow(Flow flow) { + Match target = flow.getMatch(); + + // Check if flow's match is allowed + if (!this.allowsMatch(target)) { + return false; + } + + // Now check if the flow's actions are not allowed + // Create a Match which summarizes the list of actions + if (flow.getActions() == null) { + return true; + } + Match actionMatch = new Match(); + for (Action action : flow.getActions()) { + switch (action.getType()) { + case SET_DL_TYPE: + actionMatch.setField(MatchType.DL_TYPE, + ((Integer) ((SetDlType) action).getDlType()) + .shortValue()); + break; + case SET_NW_SRC: + actionMatch.setField(MatchType.NW_SRC, ((SetNwSrc) action) + .getAddress()); + break; + case SET_NW_DST: + actionMatch.setField(MatchType.NW_DST, ((SetNwDst) action) + .getAddress()); + break; + case SET_TP_SRC: + actionMatch.setField(MatchType.TP_SRC, + ((Integer) ((SetTpSrc) action).getPort()).shortValue()); + break; + case SET_TP_DST: + actionMatch.setField(MatchType.TP_DST, + ((Integer) ((SetTpDst) action).getPort()).shortValue()); + break; + default: + // This action cannot conflict + } + } + + return this.allowsMatch(actionMatch); + } + + /** + * Returns whether the specified match is allowed + * + * @param match the match to test + * @return true if the match is allowed, false otherwise + */ + public boolean allowsMatch(Match target) { + return !target.conflictWithFilter(this.match); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ContainerServiceDependency.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ContainerServiceDependency.java new file mode 100644 index 0000000000..29e9dfabb1 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ContainerServiceDependency.java @@ -0,0 +1,247 @@ + +/* + * 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.controller.sal.core; + +/** + * @file ContainerServiceDependency.java + * + * @brief Class representing a ServiceDependency on a container + * + * Class representing a ServiceDependency on a container + */ + +import java.util.Dictionary; +import org.osgi.framework.ServiceReference; +import org.apache.felix.dm.ServiceDependency; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.Dependency; +import org.apache.felix.dm.DependencyActivation; +import org.apache.felix.dm.DependencyService; + +/** + * Class representing a ServiceDependency on a container + * + */ +public class ContainerServiceDependency implements ServiceDependency, + DependencyActivation { + private ServiceDependency m_dep; + private String containerName; + + public ContainerServiceDependency(DependencyManager manager, + String containerName) { + this.m_dep = manager.createServiceDependency(); + this.containerName = containerName; + } + + private ContainerServiceDependency(ServiceDependency explicitDependency, + String containerName) { + this.m_dep = explicitDependency; + this.containerName = containerName; + } + + @Override + public ServiceDependency setService(Class serviceName) { + this.m_dep.setService(serviceName, "(containerName=" + + this.containerName + ")"); + return this; + } + + @Override + public ServiceDependency setService(Class serviceName, String serviceFilter) { + this.m_dep.setService(serviceName, "(&(containerName=" + + this.containerName + ")" + serviceFilter + ")"); + return this; + } + + @Override + public ServiceDependency setService(String serviceFilter) { + this.m_dep.setService("(&(containerName=" + this.containerName + ")" + + serviceFilter + ")"); + return this; + } + + @Override + public ServiceDependency setService(Class serviceName, + ServiceReference serviceReference) { + this.m_dep.setService(serviceName, serviceReference); + return this; + } + + @Override + public ServiceDependency setDefaultImplementation(Object implementation) { + this.m_dep.setDefaultImplementation(implementation); + return this; + } + + @Override + public ServiceDependency setRequired(boolean required) { + this.m_dep.setRequired(required); + return this; + } + + @Override + public ServiceDependency setAutoConfig(boolean autoConfig) { + this.m_dep.setAutoConfig(autoConfig); + return this; + } + + @Override + public ServiceDependency setAutoConfig(String instanceName) { + this.m_dep.setAutoConfig(instanceName); + return this; + } + + @Override + public ServiceDependency setCallbacks(String added, String removed) { + this.m_dep.setCallbacks(added, removed); + return this; + } + + @Override + public ServiceDependency setCallbacks(String added, String changed, + String removed) { + this.m_dep.setCallbacks(added, changed, removed); + return this; + } + + @Override + public ServiceDependency setCallbacks(String added, String changed, + String removed, String swapped) { + this.m_dep.setCallbacks(added, changed, removed, swapped); + return this; + } + + @Override + public ServiceDependency setCallbacks(Object instance, String added, + String removed) { + this.m_dep.setCallbacks(instance, added, removed); + return this; + } + + @Override + public ServiceDependency setCallbacks(Object instance, String added, + String changed, String removed) { + this.m_dep.setCallbacks(instance, added, changed, removed); + return this; + } + + @Override + public ServiceDependency setCallbacks(Object instance, String added, + String changed, String removed, String swapped) { + this.m_dep.setCallbacks(instance, added, changed, removed, swapped); + return this; + } + + @Override + public ServiceDependency setPropagate(boolean propagate) { + this.m_dep.setPropagate(propagate); + return this; + } + + @Override + public ServiceDependency setPropagate(Object instance, String method) { + this.m_dep.setPropagate(instance, method); + return this; + } + + @Override + public ServiceDependency setInstanceBound(boolean isInstanceBound) { + this.m_dep.setInstanceBound(isInstanceBound); + return this; + } + + @Override + public Dependency createCopy() { + return new ContainerServiceDependency((ServiceDependency) this.m_dep + .createCopy(), this.containerName); + } + + @Override + public Dictionary getProperties() { + return this.m_dep.getProperties(); + } + + @Override + public boolean isPropagated() { + return this.m_dep.isPropagated(); + } + + @Override + public boolean isRequired() { + return this.m_dep.isRequired(); + } + + @Override + public boolean isAvailable() { + return this.m_dep.isAvailable(); + } + + @Override + public boolean isInstanceBound() { + return this.m_dep.isInstanceBound(); + } + + @Override + public boolean isAutoConfig() { + return this.m_dep.isAutoConfig(); + } + + @Override + public Class getAutoConfigType() { + return this.m_dep.getAutoConfigType(); + } + + @Override + public Object getAutoConfigInstance() { + return this.m_dep.getAutoConfigInstance(); + } + + @Override + public String getAutoConfigName() { + return this.m_dep.getAutoConfigName(); + } + + @Override + public void invokeAdded(DependencyService service) { + this.m_dep.invokeAdded(service); + } + + @Override + public void invokeRemoved(DependencyService service) { + this.m_dep.invokeRemoved(service); + } + + @Override + public String getName() { + return this.m_dep.getName(); + } + + @Override + public String getType() { + return this.m_dep.getType(); + } + + @Override + public int getState() { + return this.m_dep.getState(); + } + + @Override + public void start(DependencyService service) { + DependencyActivation a = (DependencyActivation) this.m_dep; + a.start(service); + } + + @Override + public void stop(DependencyService service) { + DependencyActivation a = (DependencyActivation) this.m_dep; + a.stop(service); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Edge.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Edge.java new file mode 100644 index 0000000000..162a4d4232 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Edge.java @@ -0,0 +1,142 @@ + +/* + * 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 + */ + +/** + * @file Edge.java + * + * @brief Describe an edge in network made of multiple SDN technologies + * + * Class that describe an Edge connecting two NodeConnector, the edge + * is directed because there is the head and the tail concept which + * implies a direction. + */ +package org.opendaylight.controller.sal.core; + +import java.io.Serializable; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * + * Class that describe an Edge connecting two NodeConnector, the edge + * is directed because there is the tail and the head concept which + * implies a direction. + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class Edge implements Serializable { + private static final long serialVersionUID = 1L; + @XmlElement + private NodeConnector tailNodeConnector; + @XmlElement + private NodeConnector headNodeConnector; + + /** + * Private constructor used for JAXB mapping + */ + private Edge() { + this.tailNodeConnector = null; + this.headNodeConnector = null; + } + + /** + * Construct the Edge + * + * @param tailNodeConnector Tail Node output connector + * @param headNodeConnector Head Node input connector + * + */ + public Edge(NodeConnector tailNodeConnector, NodeConnector headNodeConnector) + throws ConstructionException { + if (tailNodeConnector == null || headNodeConnector == null) { + throw new ConstructionException( + "Null tail or head NodeConnector supplied"); + } else { + this.tailNodeConnector = tailNodeConnector; + this.headNodeConnector = headNodeConnector; + } + } + + /** + * Copy Construct the Edge + * + * @param src Edge to copy from + * + */ + public Edge(Edge src) throws ConstructionException { + if (src != null) { + this.tailNodeConnector = new NodeConnector(src + .getTailNodeConnector()); + this.headNodeConnector = new NodeConnector(src + .getHeadNodeConnector()); + } else { + throw new ConstructionException("src supplied was null"); + } + } + + /** + * getter of edge + * + * + * @return tail NodeConnector of the edge + */ + public NodeConnector getTailNodeConnector() { + return tailNodeConnector; + } + + /** + * setter for edge + * + * @param tailNodeConnector NodeConnector to set the tail + */ + public void setTailNodeConnector(NodeConnector tailNodeConnector) { + this.tailNodeConnector = tailNodeConnector; + } + + /** + * getter of edge + * + * + * @return head NodeConnector of the edge + */ + public NodeConnector getHeadNodeConnector() { + return headNodeConnector; + } + + /** + * setter for edge + * + * @param headNodeConnector NodeConnector to set the head + */ + public void setHeadNodeConnector(NodeConnector headNodeConnector) { + this.headNodeConnector = headNodeConnector; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "(" + this.tailNodeConnector + "->" + this.headNodeConnector + + ")"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Host.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Host.java new file mode 100644 index 0000000000..f5490860d6 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Host.java @@ -0,0 +1,108 @@ + +/* + * 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.controller.sal.core; + +import java.io.Serializable; +import java.net.InetAddress; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.opendaylight.controller.sal.packet.address.DataLinkAddress; + +@XmlRootElement(name="host") +@XmlAccessorType(XmlAccessType.NONE) +public class Host implements Serializable { + private static final long serialVersionUID = 1L; + @XmlElement + private DataLinkAddress dataLayerAddress; + private InetAddress networkAddress; + + public Host() { + + } + + /** + * Create an Host representation from the combination Data Link + * layer/Network layer address, both are needed to construct the + * object. Fake value can also be provided in case are not + * existent. + * + * @param dataLayerAddress Data Link Address for the host + * @param networkAddress Network Address for the host + * + * @return the constructed object + */ + public Host(DataLinkAddress dataLayerAddress, InetAddress networkAddress) + throws ConstructionException { + if (dataLayerAddress == null) { + throw new ConstructionException("Passed null datalink address"); + } + if (networkAddress == null) { + throw new ConstructionException("Passed null network address"); + } + this.dataLayerAddress = dataLayerAddress; + this.networkAddress = networkAddress; + } + + /** + * Copy constructor + * + * @param h Host to copy values from + * + * @return constructed copy + */ + public Host(Host h) throws ConstructionException { + if (h == null) { + throw new ConstructionException("Passed null host"); + } + this.dataLayerAddress = h.getDataLayerAddress(); + this.networkAddress = h.getNetworkAddress(); + } + + /** + * @return the dataLayerAddress + */ + public DataLinkAddress getDataLayerAddress() { + return this.dataLayerAddress; + } + + /** + * @return the networkAddress + */ + public InetAddress getNetworkAddress() { + return networkAddress; + } + + @XmlElement(name = "networkAddress") + public String getNetworkAddressAsString() { + return networkAddress.getHostAddress(); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Host[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainer.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainer.java new file mode 100644 index 0000000000..5aeb5c8b2d --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainer.java @@ -0,0 +1,67 @@ + +/* + * 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 + */ + +/** + * @file IContainer.java + * + * @brief Interface used to retrieve the status of a given Container + * + * + */ + +package org.opendaylight.controller.sal.core; + +import java.util.List; +import java.util.Set; + +/** + * + * Interface used to retrieve the status of a given Container + */ +public interface IContainer { + /** + * Returns the Name of the container described + * + * @return the container Name + */ + public String getName(); + + /** + * The list of container flows associated with a container + * + * @return The list of FlowSpecs associated with the container + */ + public List getContainerFlows(); + + /** + * Return the tag on which a Node is expected to receive traffic + * for a given container. + * + * @param n The node for which we want to get the Tag + * + * @return the tag on which we expect to receive traffic on a + * given Node for a given container + */ + public short getTag(Node n); + + /** + * Return an array of all the NodeConnectors that are part of the + * container + * + * @return The array of nodeConnectors part of the container + */ + public Set getNodeConnectors(); + + /** + * Return an array of all the Nodes that are part of a container + * + * @return The array of Nodes that are part of the container + */ + public Set getNodes(); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainerAware.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainerAware.java new file mode 100644 index 0000000000..008ec59bfa --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainerAware.java @@ -0,0 +1,35 @@ + +/* + * 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.controller.sal.core; + +/** + * @file IContainerAware.java + * + * @brief Define the interface to be called when the Container is being + * created/destroyed + * + * + */ + +public interface IContainerAware { + /** + * Method invoked to signal that a container is being created + * + * @param containerName Container being created + */ + public void containerCreate(String containerName); + + /** + * Method invoked to signal that a container is being destroyed + * + * @param containerName Container being destroyed + */ + public void containerDestroy(String containerName); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainerListener.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainerListener.java new file mode 100644 index 0000000000..8ba62e234d --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/IContainerListener.java @@ -0,0 +1,79 @@ + +/* + * 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 + */ + +/** + * @file IContainerListener.java + * + * @brief Set of methods needed to listen to changes in the Container + * configuration + * + * Set of methods needed to listen to changes in the Container + * configuration + * + * + */ +package org.opendaylight.controller.sal.core; + +/** + * + * Interface used to retrieve the status of a given Container + */ +public interface IContainerListener { + /** + * Called to notify a change in the tag assigned to a switch + * + * @param containerName container for which the update has been raised + * @param n Node of the tag under notification + * @param oldTag previous version of the tag, this differ from the + * newTag only if the UpdateType is a modify + * @param newTag new value for the tag, different from oldTag only + * in case of modify operation + * @param t type of update + */ + public void tagUpdated(String containerName, Node n, short oldTag, + short newTag, UpdateType t); + + /** + * Notification raised when the container flow layout changes + * + * @param containerName container for which the update has been raised + * @param previousFlow previous value of the container flow under + * update, differs from the currentFlow only and only if it's an + * update operation + * @param currentFlow current version of the container flow differs from + * the previousFlow only in case of update + * @param t type of update + */ + public void containerFlowUpdated(String containerName, + ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t); + + /** + * Notification raised when a NodeConnector is added or removed in + * the container. + * + * @param containerName container for which the update has been raised + * @param p NodeConnector being updated + * @param t type of modification, but among the types the modify + * operation is not expected to be raised because the + * nodeConnectors are anyway immutable so this is only used to + * add/delete + */ + public void nodeConnectorUpdated(String containerName, NodeConnector p, + UpdateType t); + + /** + * Notification raised when the container mode has changed + * This notification is needed for some bundle in the default container + * to cleanup some HW state when switching from non-slicing to + * slicing case and vice-versa + * + * @param t ADDED when first container is created, REMOVED when last container is removed + */ + public void containerModeUpdated(UpdateType t); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Latency.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Latency.java new file mode 100644 index 0000000000..a7fd580b01 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Latency.java @@ -0,0 +1,105 @@ + +/* + * 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.controller.sal.core; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * @file Latency.java + * + * @brief Class representing Latency + * + * Describe a latency in picoseconds or multiple of its. + */ +@XmlRootElement +public class Latency extends Property { + private static final long serialVersionUID = 1L; + private long latency; + + public static final long LATENCYUNK = 0; + public static final long LATENCY1ns = (long) Math.pow(10, 3); + public static final long LATENCY10ns = (long) Math.pow(10, 4); + public static final long LATENCY100ns = (long) Math.pow(10, 5); + public static final long LATENCY1us = (long) Math.pow(10, 6); + public static final long LATENCY10us = (long) Math.pow(10, 7); + public static final long LATENCY100us = (long) Math.pow(10, 8); + public static final long LATENCY1ms = (long) Math.pow(10, 9); + public static final long LATENCY1s = (long) Math.pow(10, 12); + + public static final String LatencyPropName = "latency"; + + /* + * Private constructor used for JAXB mapping + */ + private Latency() { + super(LatencyPropName); + this.latency = LATENCYUNK; + } + + public Latency(long latency) { + super(LatencyPropName); + this.latency = latency; + } + + public Latency(int latency) { + super(LatencyPropName); + this.latency = (long) latency; + } + + public Latency(short latency) { + super(LatencyPropName); + this.latency = (long) latency; + } + + public Latency clone() { + return new Latency(this.latency); + } + + public long getValue() { + return this.latency; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + + sb.append("Latency["); + if (this.latency == 0) { + sb.append("UnKnown"); + } else if (this.latency < LATENCY1ns) { + sb.append(this.latency + "psec"); + } else if (this.latency < LATENCY1us) { + sb.append(Long.toString(this.latency / LATENCY1ns) + "nsec"); + } else if (this.latency < LATENCY1ms) { + sb.append(Long.toString(this.latency / LATENCY1us) + "usec"); + } else if (this.latency < LATENCY1s) { + sb.append(Long.toString(this.latency / LATENCY1ms) + "msec"); + } + + sb.append("]"); + return sb.toString(); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/MacAddress.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/MacAddress.java new file mode 100644 index 0000000000..2bfeb46248 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/MacAddress.java @@ -0,0 +1,94 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * The class contains the controller MAC address and node MAC address. + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class MacAddress extends Property { + private static final long serialVersionUID = 1L; + @XmlElement + private byte[] controllerMacAddress; + @XmlElement + private byte[] nodeMacAddress; + public static final String MacPropName = "macAddress"; + + /* + * Private constructor used for JAXB mapping + */ + private MacAddress() { + super(MacPropName); + this.controllerMacAddress = null; + this.nodeMacAddress = null; + } + + /** + * Constructor to create DatalinkAddress property which contains the + * controller MAC address and node MAC address. The property will be + * attached to a {@link org.opendaylight.controller.sal.core.Node}. + * + * @param controllerMacAddress Data Link Address for the controller + * @param nodeMacAddress Data Link Address for the node + * + * @return the constructed object + */ + public MacAddress(byte[] controllerMacAddress, byte[] nodeMacAddress) { + super(MacPropName); + + this.controllerMacAddress = controllerMacAddress; + this.nodeMacAddress = nodeMacAddress; + } + + /** + * @return the controller MAC address + */ + public byte[] getControllerMacAddress() { + return this.controllerMacAddress; + } + + /** + * @return the node MAC address + */ + public byte[] getNodeMacAddress() { + return this.nodeMacAddress; + } + + public MacAddress clone() { + return new MacAddress(this.controllerMacAddress, this.nodeMacAddress); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "MacAddress[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Name.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Name.java new file mode 100644 index 0000000000..74617c7c5b --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Name.java @@ -0,0 +1,66 @@ + +/* + * 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.controller.sal.core; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlElement; + +/** + * The class represents the Name property of an element. + * + * + */ +@XmlRootElement +@SuppressWarnings("serial") +public class Name extends Property { + @XmlElement + private String nameValue; + public static final String NamePropName = "name"; + + /* + * Private constructor used for JAXB mapping + */ + private Name() { + super(NamePropName); + this.nameValue = null; + } + + public Name(String name) { + super(NamePropName); + this.nameValue = name; + } + + public Name clone() { + return new Name(this.nameValue); + } + + public String getValue() { + return this.nameValue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Name[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Node.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Node.java new file mode 100644 index 0000000000..b199e5ce72 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Node.java @@ -0,0 +1,439 @@ + +/* + * 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 + */ + +/** + * @file Node.java + * + * @brief Describe a generic network element in multiple SDNs technologies + * + * Describe a generic network element in multiple SDNs technologies. A + * Node is identified by the pair (NodeType, NodeID), the nodetype are + * needed in order to further specify the nodeID + */ +package org.opendaylight.controller.sal.core; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.Set; +import java.math.BigInteger; + +import java.io.Serializable; +import java.lang.String; +import java.util.UUID; +import java.lang.Long; +import java.lang.Class; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.opendaylight.controller.sal.utils.HexEncode; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; + +/** + * Describe a generic network element in multiple SDNs technologies. A + * Node is identified by the pair (NodeType, NodeID), the nodetype are + * needed in order to further specify the nodeID + * + */ +@XmlAccessorType(XmlAccessType.NONE) +public class Node implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * Enum-like static class created with the purpose of identifing + * multiple type of nodes in the SDN network. The type is + * necessary to figure out to later on correctly use the + * nodeID. Using a static class instead of an Enum so we can add + * dynamically new types without changing anything in the + * surround. + */ + public static final class NodeIDType { + private static final ConcurrentHashMap compatibleType = + new ConcurrentHashMap(); + /** + * Identifier for an OpenFlow node + */ + public static String OPENFLOW = "OF"; + /** + * Identifier for a PCEP node + */ + public static String PCEP = "PE"; + /** + * Identifier for a ONEPK node + */ + public static String ONEPK = "PK"; + /** + * Identifier for a node in a non-SDN network + */ + public static String PRODUCTION = "PR"; + + // Pre-populated types, just here for convenience and ease of + // unit-testing, but certainly those could live also outside. + static { + compatibleType.put(OPENFLOW, Long.class); + compatibleType.put(PCEP, UUID.class); + compatibleType.put(ONEPK, String.class); + compatibleType.put(PRODUCTION, String.class); + } + + /** + * Return the type of the class expected for the + * NodeID, it's used for validity check in the constructor + * + * @param nodeType the type of the node we want to check + * compatibility for + * + * @return The Class which is supposed to instantiate the ID + * for the NodeID + */ + public static Class getClassType(String nodeType) { + return compatibleType.get(nodeType); + } + + /** + * Returns all the registered nodeIDTypes currently available + * + * @return The current registered NodeIDTypes + */ + public static Set values() { + return compatibleType.keySet(); + } + + /** + * Register a new ID for which Node can be created + * + * @param type, the new type being registered + * @param compatibleID, the type of class to be accepted as ID + * + * @return true if registered, false otherwise + */ + public static boolean registerIDType(String type, + Class compatibleID) { + if (compatibleType.get(type) != null) { + return false; + } else { + compatibleType.put(type, compatibleID); + return true; + } + } + + /** + * UNRegister a new ID for which Node can be created + * + * @param type, the type being UN-registered + * + */ + public static void unRegisterIDType(String type) { + compatibleType.remove(type); + } + } + + // This is the identity of the Node a (Type,ID) pair!, the full + // essence of this class. + private Object nodeID; + private String nodeType; + + // Shadow value for unmarshalling + private String nodeIDString; + + /** + * Private constructor used for JAXB mapping + */ + private Node() { + this.nodeID = null; + this.nodeType = null; + this.nodeIDString = null; + } + + /** + * Constructor for the Node objects, it validate the input so if + * the ID passed is not of the type expected accordingly to the + * type an exception is raised. + * + * @param nodeType Type of the node we are building + * @param id ID used by the SDN technology to identify the node + * + */ + public Node(String nodeType, Object id) throws ConstructionException { + if (NodeIDType.getClassType(nodeType) != null && + NodeIDType.getClassType(nodeType).isInstance(id)) { + this.nodeType = nodeType; + this.nodeID = id; + } else { + throw new ConstructionException("Type of incoming object:" + + id.getClass() + " not compatible with expected type:" + + NodeIDType.getClassType(nodeType)); + } + } + + /** + * Copy Constructor for the Node objects. + * + * @param src type of nodes to copy from + * + */ + public Node(Node src) throws ConstructionException { + if (src != null) { + this.nodeType = src.getType(); + // Here we can reference the object because that is + // supposed to be an immutable identifier as well like a + // UUID/Integer and so on, hence no need to create a copy + // of it + this.nodeID = src.getID(); + } else { + throw + new ConstructionException("Null incoming object to copy from"); + } + } + + /** + * getter for node type + * + * + * @return The node Type for this Node object + */ + @XmlAttribute(name = "type") + public String getType() { + return this.nodeType; + } + + /** + * fill the current object from the string parameters passed, will + * be only used by JAXB + * + * @param typeStr string representing the type of the Node + * @param IDStr String representation of the ID + */ + private void fillmeFromString(String typeStr, String IDStr) { + if (typeStr == null) { + return; + } + + if (IDStr == null) { + return; + } + + this.nodeType = typeStr; + if (typeStr.equals(NodeIDType.OPENFLOW)) { + this.nodeID = Long.valueOf(HexEncode.stringToLong(IDStr)); + } else if (typeStr.equals(NodeIDType.ONEPK)) { + this.nodeID = IDStr; + } else if (typeStr.equals(NodeIDType.PCEP)) { + this.nodeID = UUID.fromString(IDStr); + } else if (typeStr.equals(NodeIDType.PRODUCTION)) { + this.nodeID = IDStr; + } else { + // We need to lookup via OSGi service registry for an + // handler for this + } + } + + /** + * Private setter for nodeType to be called by JAXB not by anyone + * else, Node is immutable + * + * @param type of node to be set + */ + private void setType(String type) { + this.nodeType = type; + if (this.nodeIDString != null) { + this.fillmeFromString(type, this.nodeIDString); + } + } + + /** + * getter for node ID + * + * + * @return The node ID for this Node object + */ + public Object getID() { + return this.nodeID; + } + + /** + * Getter for the node ID in string format + * + * @return The nodeID in string format + */ + @XmlAttribute(name = "id") + public String getNodeIDString() { + if (this.nodeType.equals(NodeIDType.OPENFLOW)) { + return HexEncode.longToHexString((Long) this.nodeID); + } else { + return this.nodeID.toString(); + } + } + + /** + * private setter to be used by JAXB + * + * @param nodeIDString String representation for NodeID + */ + private void setNodeIDString(String nodeIDString) { + this.nodeIDString = nodeIDString; + if (this.nodeType != null) { + this.fillmeFromString(this.nodeType, nodeIDString); + } + } + + @Override + public int hashCode() { + return new HashCodeBuilder(163841, 56473) + .append(nodeType) + .append(nodeID) + .hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { return false; } + if (obj == this) { return true; } + if (obj.getClass() != getClass()) { + return false; + } + Node rhs = (Node)obj; + return new EqualsBuilder() + .append(this.getType(), rhs.getType()) + .append(this.getID(), rhs.getID()) + .isEquals(); + } + + @Override + public String toString() { + if (this.nodeType.equals(NodeIDType.OPENFLOW)) { + return this.nodeType.toString() + "|" + + HexEncode.longToHexString((Long) this.nodeID); + } else { + return this.nodeType.toString() + "|" + this.nodeID.toString(); + } + } + + /** + * Static method to get back a Node from a string + * + * @param str string formatted in toString mode that can be + * converted back to a Node format. + * + * @return a Node if succed or null if no + */ + public static Node fromString(String str) { + if (str == null) { + return null; + } + + String parts[] = str.split("\\|"); + if (parts.length != 2) { + // Try to guess from a String formatted as a long because + // for long time openflow has been prime citizen so lets + // keep this legacy for now + String numStr = str.toUpperCase(); + + Long ofNodeID = null; + if (numStr.startsWith("0X")) { + // Try as an hex number + try { + BigInteger b = new BigInteger( + numStr.replaceFirst("0X", ""), 16); + ofNodeID = Long.valueOf(b.longValue()); + } catch (Exception ex) { + ofNodeID = null; + } + } else { + // Try as a decimal number + try { + BigInteger b = new BigInteger(numStr); + ofNodeID = Long.valueOf(b.longValue()); + } catch (Exception ex) { + ofNodeID = null; + } + } + + // Startegy #3 parse as HexLong + if (ofNodeID == null) { + try { + ofNodeID = Long.valueOf(HexEncode.stringToLong(numStr)); + } catch (Exception ex) { + ofNodeID = null; + } + } + + // We ran out of ideas ... return null + if (ofNodeID == null) { + return null; + } + + // Lets return the cooked up NodeID + try { + return new Node(NodeIDType.OPENFLOW, ofNodeID); + } catch (ConstructionException ex) { + return null; + } + } + + String typeStr = parts[0]; + String IDStr = parts[1]; + + return fromString(typeStr, IDStr); + } + + /** + * Static method to get back a Node from a pair of strings, the + * first one being the Type representation, the second one being + * the ID string representation, expected to be heavily used in + * northbound API. + * + * @param type, the type of the node we are parsing + * @param id, the string representation of the node id + * + * @return a Node if succed or null if no + */ + public static Node fromString(String typeStr, String IDStr) { + if (typeStr == null) { + return null; + } + + if (IDStr == null) { + return null; + } + + if (typeStr.equals(NodeIDType.OPENFLOW)) { + try { + Long ID = Long.valueOf(HexEncode.stringToLong(IDStr)); + return new Node(typeStr, ID); + } catch (Exception ex) { + return null; + } + } else if (typeStr.equals(NodeIDType.ONEPK)) { + try { + return new Node(typeStr, IDStr); + } catch (Exception ex) { + return null; + } + } else if (typeStr.equals(NodeIDType.PCEP)) { + try { + UUID ID = UUID.fromString(IDStr); + return new Node(typeStr, ID); + } catch (Exception ex) { + return null; + } + } else if (typeStr.equals(NodeIDType.PRODUCTION)) { + try { + return new Node(typeStr, IDStr); + } catch (Exception ex) { + return null; + } + } else { + // We need to lookup via OSGi service registry for an + // handler for this + } + return null; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeConnector.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeConnector.java new file mode 100644 index 0000000000..bbe952ddea --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/NodeConnector.java @@ -0,0 +1,589 @@ + +/* + * 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 + */ + +/** + * @file NodeConnector.java + * + * @brief Describe a generic network element attachment points, + * attached to one Node, the NodeConnector is formed by the pair + * (NodeConnectorType, NodeConnectorID) because each SDN technlogy can + * identify an attachment point on the Node in different way. + * + */ +package org.opendaylight.controller.sal.core; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import java.util.concurrent.ConcurrentHashMap; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlAttribute; + +/** + * Describe a generic network element attachment points, + * attached to one Node, the NodeConnector is formed by the pair + * (NodeConnectorType, NodeConnectorID) because each SDN technology can + * identify an attachment point on the Node in different way. + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class NodeConnector implements Serializable { + private static final long serialVersionUID = 1L; + public static final Short SPECIALNODECONNECTORID = (short) 0; + + /** + * Enumerate the different types of NodeConnectors supported by the class + * + */ + public static class NodeConnectorIDType { + private static final + ConcurrentHashMap> compatibleType = + new ConcurrentHashMap>(); + /** + * Represent a special port pointing toward the controller, + * this is to send data packets toward the controller from + * data plane. + */ + public static String CONTROLLER = "CTRL"; + /** + * Special port describing ALL the ports in the system, + * should be used for flooding like mechanism but better + * to be carefull with it + */ + public static String ALL = "ALL"; + /** + * Describe the local networking stack of the node + * on which the packet is destined. Yet another special port + */ + public static String SWSTACK = "SW"; + /** + * Describe a special destination that invoke the + * traditional HW forwarding on platforms that has this + * provision. + */ + public static String HWPATH = "HW"; + public static String OPENFLOW = "OF"; + public static String PCEP = "PE"; + public static String ONEPK = "PK"; + public static String OPENFLOW2PCEP = "O2E"; + public static String PCEP2OPENFLOW = "E2O"; + public static String OPENFLOW2ONEPK = "O2K"; + public static String ONEPK2OPENFLOW = "K2O"; + public static String PCEP2ONEPK = "E2K"; + public static String ONEPK2PCEP = "K2E"; + public static String PRODUCTION = "PR"; + + // Initialize the map with some well known, even though all of + // them could be siting outside of here, but it's convenient + // for Unit Testing coverage + static { + compatibleType.put(CONTROLLER, + new ImmutablePair(Short.class, null)); + compatibleType.put(ALL, + new ImmutablePair(Short.class, null)); + compatibleType.put(SWSTACK, + new ImmutablePair(Short.class, null)); + compatibleType.put(HWPATH, + new ImmutablePair(Short.class, null)); + compatibleType.put(OPENFLOW, + new ImmutablePair(Short.class, + Node.NodeIDType.OPENFLOW)); + compatibleType.put(PCEP, + new ImmutablePair(Integer.class, + Node.NodeIDType.PCEP)); + compatibleType.put(ONEPK, + new ImmutablePair(String.class, + Node.NodeIDType.ONEPK)); + compatibleType.put(OPENFLOW2PCEP, + new ImmutablePair(Short.class, + Node.NodeIDType.OPENFLOW)); + compatibleType.put(OPENFLOW2ONEPK, + new ImmutablePair(Short.class, + Node.NodeIDType.OPENFLOW)); + compatibleType.put(PCEP2OPENFLOW, + new ImmutablePair(Integer.class, + Node.NodeIDType.PCEP)); + compatibleType.put(PCEP2ONEPK, + new ImmutablePair(Integer.class, + Node.NodeIDType.PCEP)); + compatibleType.put(ONEPK2OPENFLOW, + new ImmutablePair(String.class, + Node.NodeIDType.ONEPK)); + compatibleType.put(ONEPK2PCEP, + new ImmutablePair(String.class, + Node.NodeIDType.ONEPK)); + compatibleType.put(PRODUCTION, + new ImmutablePair(String.class, + Node.NodeIDType.PRODUCTION)); + } + + /** + * Return the type of the class expected for the + * NodeConnectorID, it's used for validity check in the constructor + * + * @param type, the type of the NodeConnector for which we + * want to retrieve the compatible class to be used as ID. + * + * @return The Class which is supposed to instantiate the ID + * for the NodeConnectorID + */ + public static Class getClassType(String type) { + if (compatibleType.get(type) == null) { + return null; + } + return compatibleType.get(type).getLeft(); + } + + /** + * Return the NodeIDType compatible with this NodeConnector, + * in fact you cannot attach for example a PCEP NodeConnector + * to an OpenFlow Node. + * + * @param type, the type of the NodeConnector for which we + * want to retrieve the compatible class to be used as ID. + * + * @return The ID of the compatible Node + */ + public static String getCompatibleNode(String type) { + if (compatibleType.get(type) == null) { + return null; + } + return compatibleType.get(type).getRight(); + } + + /** + * Register a new ID for which Node can be created + * + * @param type, the new type being registered + * @param compatibleID, the type of class to be accepted as ID + * @param compatibleNode, the type of Node with which this + * NodeConnector is compatible + * + * @return true if registered, false otherwise + */ + public static boolean registerIDType(String type, + Class compatibleID, + String compatibleNode) { + if (compatibleType.get(type) != null) { + return false; + } else { + compatibleType.put(type, new ImmutablePair(compatibleID, + compatibleNode)); + return true; + } + } + + /** + * UNRegister a new ID for which Node can be created + * + * @param type, the type being UN-registered + * + */ + public static void unRegisterIDType(String type) { + compatibleType.remove(type); + } + } + + // Elements that constitute the NodeConnector + private Object nodeConnectorID; + private String nodeConnectorType; + @XmlElement(name = "node") + private Node nodeConnectorNode; + + // Helper field for JAXB + private String nodeConnectorIDString; + + /** + * Private constructor used for JAXB mapping + */ + private NodeConnector() { + this.nodeConnectorIDString = null; + this.nodeConnectorID = null; + this.nodeConnectorType = null; + this.nodeConnectorNode = null; + } + + /** + * Create a NodeConnector from the component element. The + * constructor make sure the NodeConnector type is congruent with + * the Node used and also the NodeConnector ID is of type expected + * + * @param nodeConnectorType Type of the NodeConnector + * @param id ID portion of the NodeConnector + * @param node Node to which the NodeConnector is attached too + * + */ + public NodeConnector(String nodeConnectorType, Object id, + Node node) throws ConstructionException { + // In case of compatible type being null then assume that this + // port can be attached on any node. + String compatibleNode = + NodeConnectorIDType.getCompatibleNode(nodeConnectorType); + if (NodeConnectorIDType.getClassType(nodeConnectorType) != null && + NodeConnectorIDType.getClassType(nodeConnectorType).isInstance(id) && + (compatibleNode == null || + node.getType().equals(compatibleNode))) { + this.nodeConnectorType = nodeConnectorType; + this.nodeConnectorID = id; + this.nodeConnectorNode = node; + } else { + throw new ConstructionException("Type of incoming object:" + + id.getClass() + " not compatible with expected type:" + + NodeConnectorIDType.getClassType(nodeConnectorType) + + " or Node type incompatible:" + node.getType()); + } + } + + /** + * Copy constructor for NodeConnector + * + * @param src NodeConnector to copy from + * + */ + public NodeConnector(NodeConnector src) throws ConstructionException { + if (src != null) { + this.nodeConnectorType = src.getType(); + // Here we can reference the object because that is + // supposed to be an immutable identifier as well like a + // UUID/Integer and so on, hence no need to create a copy + // of it + this.nodeConnectorID = src.getID(); + this.nodeConnectorNode = new Node(src.getNode()); + } else { + throw + new ConstructionException("Null incoming object to copy from"); + } + } + + /** + * getter method for NodeConnector + * + * + * @return the NodeConnectorType of this object + */ + @XmlAttribute(name = "type") + public String getType() { + return this.nodeConnectorType; + } + + /** + * fill the current object from the string parameters passed, will + * be only used by JAXB + * + * @param typeStr string representing the type of the Node + * @param IDStr String representation of the ID + */ + private void fillmeFromString(String typeStr, String IDStr) { + if (typeStr == null) { + return; + } + + if (IDStr == null) { + return; + } + + this.nodeConnectorType = typeStr; + if (typeStr.equals(NodeConnectorIDType.OPENFLOW) || + typeStr.equals(NodeConnectorIDType.OPENFLOW2ONEPK) || + typeStr.equals(NodeConnectorIDType.OPENFLOW2PCEP)) { + try { + Short ID = Short.parseShort(IDStr); + this.nodeConnectorID = ID; + } catch (Exception ex) { + return; + } + } else if (typeStr.equals(NodeConnectorIDType.ONEPK) || + typeStr.equals(NodeConnectorIDType.ONEPK2OPENFLOW) || + typeStr.equals(NodeConnectorIDType.ONEPK2PCEP) || + typeStr.equals(NodeConnectorIDType.PRODUCTION)) { + try { + this.nodeConnectorID = IDStr; + } catch (Exception ex) { + return; + } + } else if (typeStr.equals(NodeConnectorIDType.PCEP) || + typeStr.equals(NodeConnectorIDType.PCEP2ONEPK) || + typeStr.equals(NodeConnectorIDType.PCEP2OPENFLOW)) { + try { + Integer ID = Integer.parseInt(IDStr); + this.nodeConnectorID = ID; + } catch (Exception ex) { + return; + } + } else { + // Lookup via OSGi service registry + } + } + + /** + * Private setter for nodeConnectorType to be called by JAXB not by anyone + * else, NodeConnector is immutable + * + * @param type of node to be set + */ + private void setType(String type) { + this.nodeConnectorType = type; + if (this.nodeConnectorIDString != null) { + this.fillmeFromString(type, this.nodeConnectorIDString); + } + } + + /** + * getter method for NodeConnector + * + * + * @return the NodeConnector ID of this object + */ + public Object getID() { + return this.nodeConnectorID; + } + + /** + * getter method for NodeConnector ID in string format. + * + * + * @return the NodeConnector ID of this object in String format + */ + @XmlAttribute(name = "id") + public String getNodeConnectorIDString() { + return this.nodeConnectorID.toString(); + } + + /** + * private setter to be used by JAXB + * + * @param nodeConnectorIDString String representation for NodeConnectorID + */ + private void setNodeConnectorIDString(String IDStr) { + this.nodeConnectorIDString = IDStr; + if (this.nodeConnectorType != null) { + this.fillmeFromString(this.nodeConnectorType, IDStr); + } + } + + /** + * getter method for NodeConnector + * + * + * @return the Node of this object + */ + public Node getNode() { + return this.nodeConnectorNode; + } + + @Override + public int hashCode() { + return new HashCodeBuilder(63389, 4951) + .append(nodeConnectorType) + .append(nodeConnectorID) + .append(nodeConnectorNode) + .hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { return false; } + if (obj == this) { return true; } + if (obj.getClass() != getClass()) { + return false; + } + NodeConnector rhs = (NodeConnector)obj; + return new EqualsBuilder() + .append(this.getType(), rhs.getType()) + .append(this.getID(), rhs.getID()) + .append(this.getNode(), rhs.getNode()) + .isEquals(); + } + + @Override + public String toString() { + return this.getNodeConnectorIdAsString() + "@" + this.nodeConnectorNode; + } + + /** + * A String representation of the NodeConnector without + * the Node context + * + * @return A String representation of the NodeConnector without + * the Node context + */ + public String getNodeConnectorIdAsString() { + if (this.nodeConnectorType + .equals(NodeConnectorIDType.CONTROLLER) || + this.nodeConnectorType + .equals(NodeConnectorIDType.ALL) || + this.nodeConnectorType + .equals(NodeConnectorIDType.SWSTACK) || + this.nodeConnectorType + .equals(NodeConnectorIDType.HWPATH)) { + return this.nodeConnectorType.toString(); + } else { + return this.nodeConnectorType.toString() + "|" + + this.nodeConnectorID.toString(); + } + } + + /** + * return a NodeConnector from a string + * + * @param str String to be parsed in a NodeConnector + * + * @return the NodeConnector if parse is succesfull, null otherwise + */ + public static NodeConnector fromString(String str) { + if (str == null) { + return null; + } + String parts[] = str.split("\\@"); + if (parts.length != 2) { + return null; + } + // Now get the Node from the Node portion + Node n = Node.fromString(parts[1]); + if (n == null) { + return null; + } + return fromStringNoNode(parts[0], n); + } + + /** + * return a NodeConnector from a string not containing explicitely + * the Node portion which has to be supplied as parameter + * + * @param str String to be parsed in a NodeConnector + * @param n Node to which the NodeConnector is attached + * + * @return the NodeConnector if parse is succesfull, null otherwise + */ + public static NodeConnector fromStringNoNode(String str, Node n) { + if (str == null) { + return null; + } + String nodeConnectorParts[] = str.split("\\|"); + if (nodeConnectorParts.length != 2) { + // Try to guess from a String formatted as a short because + // for long time openflow has been prime citizen so lets + // keep this legacy for now + String numStr = str.toUpperCase(); + + Short ofPortID = null; + // Try as an decimal/hex number + try { + ofPortID = Short.decode(numStr); + } catch (Exception ex) { + ofPortID = null; + } + + // Lets try the special ports we know about + if (ofPortID == null) { + try { + if (str.equalsIgnoreCase(NodeConnectorIDType.CONTROLLER + .toString())) { + return new NodeConnector( + NodeConnectorIDType.CONTROLLER, + SPECIALNODECONNECTORID, n); + } + if (str.equalsIgnoreCase(NodeConnectorIDType.HWPATH + .toString())) { + return new NodeConnector(NodeConnectorIDType.HWPATH, + SPECIALNODECONNECTORID, n); + } + if (str.equalsIgnoreCase(NodeConnectorIDType.SWSTACK + .toString())) { + return new NodeConnector(NodeConnectorIDType.SWSTACK, + SPECIALNODECONNECTORID, n); + } + if (str + .equalsIgnoreCase(NodeConnectorIDType.ALL + .toString())) { + return new NodeConnector(NodeConnectorIDType.ALL, + SPECIALNODECONNECTORID, n); + } + } catch (ConstructionException ex) { + return null; + } + return null; + } + + // Lets return the cooked up NodeID + try { + return new NodeConnector(NodeConnectorIDType.OPENFLOW, + ofPortID, n); + } catch (ConstructionException ex) { + return null; + } + } + + String typeStr = nodeConnectorParts[0]; + String IDStr = nodeConnectorParts[1]; + return fromStringNoNode(typeStr, IDStr, n); + } + + /** + * return a NodeConnector from a pair (type, ID) in string format + * not containing explicitely the Node portion which has to be + * supplied as parameter + * + * @param typeStr type String to be parsed in a NodeConnector + * @param IDStr ID String portion to be parsed in a NodeConnector + * @param n Node to which the NodeConnector is attached + * + * @return the NodeConnector if parse is succesfull, null otherwise + */ + public static NodeConnector fromStringNoNode(String typeStr, String IDStr, + Node n) { + if (typeStr == null) { + return null; + } + if (IDStr == null) { + return null; + } + + if (typeStr.equals(NodeConnectorIDType.OPENFLOW) || + typeStr.equals(NodeConnectorIDType.OPENFLOW2ONEPK) || + typeStr.equals(NodeConnectorIDType.OPENFLOW2PCEP)) { + try { + Short ID = Short.parseShort(IDStr); + return new NodeConnector(typeStr, ID, n); + } catch (Exception ex) { + return null; + } + } else if (typeStr.equals(NodeConnectorIDType.ONEPK) || + typeStr.equals(NodeConnectorIDType.ONEPK2OPENFLOW) || + typeStr.equals(NodeConnectorIDType.ONEPK2PCEP) || + typeStr.equals(NodeConnectorIDType.PRODUCTION)) { + try { + return new NodeConnector(typeStr, IDStr, n); + } catch (Exception ex) { + return null; + } + } else if (typeStr.equals(NodeConnectorIDType.PCEP) || + typeStr.equals(NodeConnectorIDType.PCEP2ONEPK) || + typeStr.equals(NodeConnectorIDType.PCEP2OPENFLOW)) { + try { + Integer ID = Integer.parseInt(IDStr); + return new NodeConnector(typeStr, ID, n); + } catch (Exception ex) { + return null; + } + } else { + // Lookup via OSGi service registry + } + return null; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Path.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Path.java new file mode 100644 index 0000000000..5584cd9461 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Path.java @@ -0,0 +1,154 @@ + +/* + * 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 + */ + +/** + * @file Path.java + * + * @brief Describe a path as a sequence of Edge such that from + * each of its Tail Node there is an link to the next Head Node in the sequence + * + */ +package org.opendaylight.controller.sal.core; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * Describe a path as a sequence of Edge such that from + * each of its Tail Node there is an link to the next Head Node in the + * sequence + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class Path implements Serializable { + private static final long serialVersionUID = 1L; + @XmlElement + private List edges; + + /** + * Private constructor used for JAXB mapping + */ + private Path() { + this.edges = null; + } + + /** + * Construct an object representing a path, the constructor will + * check if the passed list of edges is such that for every + * consecutive edges the tailnode of the first edge coincide with + * the head node of the subsequent in order for connectivity to be there. + * + * @param edges Edges of the path + * + */ + public Path(List edges) throws ConstructionException { + // Lets check if the list of edges is such that the tail node + // of an edge is also the head node of the subsequent one + boolean sequential = true; + if (edges.size() >= 2) { + for (int i = 0; i < edges.size() - 1; i++) { + Edge current = edges.get(i); + Edge next = edges.get(i + 1); + if (!current.getHeadNodeConnector().getNode() + .equals( + next.getTailNodeConnector() + .getNode())) { + sequential = false; + } + } + } else if (edges.size() == 0) { + throw new ConstructionException("Path is empty"); + } + + if (!sequential) { + throw new ConstructionException("Path is not sequential"); + } + + this.edges = edges; + } + + /** + * Copy Construct for a path + * + * @param src Path to copy from + * + */ + public Path(Path src) throws ConstructionException { + if (src != null) { + this.edges = new LinkedList(src.getEdges()); + } else { + throw new ConstructionException("src supplied was null"); + } + } + + /** + * get the First Node of the path + * + * + * @return The start Node of the Path + */ + public Node getStartNode() { + return this.edges.get(0).getTailNodeConnector().getNode(); + } + + /** + * get the Last Node of the path + * + * + * @return The last Node of the Path + */ + public Node getEndNode() { + return this.edges.get(this.edges.size() - 1).getHeadNodeConnector() + .getNode(); + } + + /** + * getter method for the Path + * + * + * @return Return the list of edges that constitue the Path + */ + public List getEdges() { + return this.edges; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < this.edges.size(); i++) { + if (i != 0) { + // add the comma to the previous element + sb.append(","); + } + sb.append(this.edges.get(i).toString()); + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/PeerBandwidth.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/PeerBandwidth.java new file mode 100644 index 0000000000..557e2b3dd2 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/PeerBandwidth.java @@ -0,0 +1,66 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * @file PeerBandWidth.java + * + * @brief Class representing peer bandwidth + * + * Describes peer Bandwidth of peer element. It's intended in multiple of + * bits per seconds. + */ +@XmlRootElement +public class PeerBandwidth extends Bandwidth { + private static final long serialVersionUID = 1L; + + public static final String PeerBandwidthPropName = "peerBandwidth"; + + public PeerBandwidth(long value) { + super(PeerBandwidthPropName); + this.bandwidthValue = value; + } + + /* + * Private constructor used for JAXB mapping + */ + private PeerBandwidth() { + super(PeerBandwidthPropName); + this.bandwidthValue = 0; + } + + public PeerBandwidth clone() { + return new PeerBandwidth(this.bandwidthValue); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("PeerBandWidth["); + sb.append(super.toString()); + sb.append("]"); + return sb.toString(); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java new file mode 100644 index 0000000000..9e4475e071 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java @@ -0,0 +1,82 @@ + +/* + * 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.controller.sal.core; + +import java.io.Serializable; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlElement; + +/** + * @file Property.java + * + * @brief Abstract base class for a Property that can be attached to + * any sal core element + * + * Abstract base class for a Property that can be attached to any sal + * core element + */ + +/** + * Abstract base class for a Property that can be attached to any sal + * core element + * + */ +@XmlRootElement +@XmlSeeAlso({ Config.class, Name.class, State.class, TimeStamp.class, + Latency.class, Bandwidth.class, Tier.class, Actions.class, + AdvertisedBandwidth.class, Buffers.class, Capabilities.class, + MacAddress.class, PeerBandwidth.class, SupportedBandwidth.class, + Tables.class }) +abstract public class Property implements Serializable { + private static final long serialVersionUID = 1L; + private String name; + + /** + * Private constructor used for JAXB mapping + */ + private Property() { + this.name = null; + } + + protected Property(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + /** + * Used to copy the Property in a polymorphic way + * + * + * @return A clone of this Property + */ + abstract public Property clone(); + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Property[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/State.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/State.java new file mode 100644 index 0000000000..693abd85d5 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/State.java @@ -0,0 +1,70 @@ + +/* + * 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.controller.sal.core; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlElement; + +/** + * The class represents the State property of an Edge + * + * + */ +@XmlRootElement +@SuppressWarnings("serial") +public class State extends Property { + @XmlElement + private short stateValue; + + public static final short EDGE_DOWN = 0; + public static final short EDGE_UP = 1; + public static final short EDGE_UNK = 0x7fff; + public static final String StatePropName = "state"; + + /* + * Private constructor used for JAXB mapping + */ + private State() { + super(StatePropName); + this.stateValue = EDGE_UNK; + } + + public State(short state) { + super(StatePropName); + this.stateValue = state; + } + + public State clone() { + return new State(this.stateValue); + } + + public short getValue() { + return this.stateValue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "State[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/SupportedBandwidth.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/SupportedBandwidth.java new file mode 100644 index 0000000000..969813ca08 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/SupportedBandwidth.java @@ -0,0 +1,68 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * @file SupportedBandWidth.java + * + * @brief Class representing supported bandwidth + * + * Describes Supported Bandwidth which could be of a link or whatever could have + * bandwidth as description. It's intended in multiple of bits per + * seconds. + */ +@XmlRootElement +public class SupportedBandwidth extends Bandwidth { + private static final long serialVersionUID = 1L; + public static final String SupportedBandwidthPropName = "supportedBandwidth"; + + public SupportedBandwidth(long value) { + super(SupportedBandwidthPropName); + this.bandwidthValue = value; + } + + /* + * Private constructor used for JAXB mapping + */ + private SupportedBandwidth() { + super(SupportedBandwidthPropName); + this.bandwidthValue = 0; + } + + public SupportedBandwidth clone() { + return new SupportedBandwidth(this.bandwidthValue); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("SupportedBandWidth["); + sb.append(super.toString()); + sb.append("]"); + return sb.toString(); + } + + +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tables.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tables.java new file mode 100644 index 0000000000..4775aa8712 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tables.java @@ -0,0 +1,74 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * @file Tables.java + * + * @brief Class representing tables + * + * Describes supported # of datapath tables + */ +@XmlRootElement +public class Tables extends Property { + private static final long serialVersionUID = 1L; + @XmlElement + private byte tablesValue; + + public static final String TablesPropName = "tables"; + /** + * Construct a Tables property + * + * @param tables the Tables + * @return Constructed object + */ + public Tables(byte tables) { + super(TablesPropName); + this.tablesValue = tables; + } + + /* + * Private constructor used for JAXB mapping + */ + private Tables() { + super(TablesPropName); + this.tablesValue = 0; + } + + public Tables clone() { + return new Tables(this.tablesValue); + } + + public byte getValue() { + return this.tablesValue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Tables[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tier.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tier.java new file mode 100644 index 0000000000..89db9aab24 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Tier.java @@ -0,0 +1,66 @@ + +/* + * 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.controller.sal.core; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * The class represents the Tier property of a node + * + * + */ +@XmlRootElement +@SuppressWarnings("serial") +public class Tier extends Property { + @XmlElement + private int tierValue; + public static final String TierPropName = "tier"; + + public Tier(int tier) { + super(TierPropName); + this.tierValue = tier; + } + + /* + * Private constructor used for JAXB mapping + */ + private Tier() { + super(TierPropName); + this.tierValue = 0; + } + + public Tier clone() { + return new Tier(this.tierValue); + } + + public int getValue() { + return this.tierValue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Tier[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/TimeStamp.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/TimeStamp.java new file mode 100644 index 0000000000..cfdceac822 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/TimeStamp.java @@ -0,0 +1,90 @@ + +/* + * 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.controller.sal.core; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlElement; + +/** + * @file TimeStamp.java + * + * @brief Class representing a TimeStamp + * + * A property describing a timestamp based following the rules of + * java.util.Date, also given the time stamp represent the time when + * something happened, then a name is attached to this property so + * to qualify what are we talking about + */ +@XmlRootElement +public class TimeStamp extends Property { + private static final long serialVersionUID = 1L; + @XmlElement + private long timestamp; + @XmlElement + private String timestampName; + + public static final String TimeStampPropName = "timeStamp"; + + /** + * Construct a TimeStamp proporty + * + * @param timestamp the time stampt we want to describe in "epoch" + * format following the rules of java.util.Date + * @param timestampName A qualifier for the timestamp, for example + * "JoinTime" or any even qualifier could come up + * + * @return Constructed object + */ + public TimeStamp(long timestamp, String timestampName) { + super(TimeStampPropName); + this.timestamp = timestamp; + this.timestampName = timestampName; + } + + /* + * Private constructor used for JAXB mapping + */ + private TimeStamp() { + super(TimeStampPropName); + this.timestamp = 0; + this.timestampName = null; + } + + public TimeStamp clone() { + return new TimeStamp(this.timestamp, this.timestampName); + } + + public long getValue() { + return this.timestamp; + } + + public String getTimeStampName() { + return this.timestampName; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "TimeStamp[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/UpdateType.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/UpdateType.java new file mode 100644 index 0000000000..84883c6adc --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/UpdateType.java @@ -0,0 +1,37 @@ + +/* + * 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.controller.sal.core; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * @file UpdateType.java + * + * @brief Describes update types + * + */ +public enum UpdateType { + ADDED("added"), REMOVED("removed"), CHANGED("changed"); + + private String name; + + UpdateType(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + @Override + public String toString() { + return "UpdateType[" + ReflectionToStringBuilder.toString(this) + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/discovery/IDiscoveryService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/discovery/IDiscoveryService.java new file mode 100644 index 0000000000..3dda38ef56 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/discovery/IDiscoveryService.java @@ -0,0 +1,33 @@ + +/* + * 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.controller.sal.discovery; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.Edge; +import org.opendaylight.controller.sal.core.Property; +import org.opendaylight.controller.sal.core.UpdateType; + +/** + * The interface class provides the methods to notify the listener when an edge + * is added/deleted/changed + */ +public interface IDiscoveryService { + /** + * The methods is called when an edge is added/deleted/changed + * + * @param edge {@link org.opendaylight.controller.sal.core.Edge} being updated + * @param type {@link org.opendaylight.controller.sal.core.UpdateType} + * @param props set of {@link org.opendaylight.controller.sal.core.Property} like + * {@link org.opendaylight.controller.sal.core.Bandwidth} and/or + * {@link org.opendaylight.controller.sal.core.Latency} etc. + */ + public void notifyEdge(Edge edge, UpdateType type, Set props); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java new file mode 100644 index 0000000000..16c85a105a --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java @@ -0,0 +1,263 @@ + +/* + * 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.controller.sal.flowprogrammer; + +import java.net.Inet6Address; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.action.Action; +import org.opendaylight.controller.sal.action.ActionType; +import org.opendaylight.controller.sal.action.SetDlType; +import org.opendaylight.controller.sal.action.SetNwDst; +import org.opendaylight.controller.sal.action.SetNwSrc; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.utils.EtherTypes; + +/** + * Represent a flow: match + actions + flow specific properties + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class Flow implements Cloneable { + @XmlElement + private Match match; + @XmlElement + private List actions; + @XmlElement + private short priority; + @XmlElement + private short idleTimeout; + @XmlElement + private short hardTimeout; + @XmlElement + private long id; // unique identifier for this flow + + public Flow() { + match = null; + actions = null; + } + + public Flow(Match match, List actions) { + if (match.isIPv4() && actionsAreIPv6()) { + try { + throw new Exception("Conflicting Match and Action list"); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + this.match = match; + this.actions = actions; + } + } + + /** + * Return a copy of the Match configured on this flow + * + * @return + */ + public Match getMatch() { + return match.clone(); + } + + /** + * Set the Match for this flow + * This operation will overwrite an existing Match if present + * + * @param match + */ + public void setMatch(Match match) { + this.match = match; + } + + /** + * Returns a copy of the actions list of this flow + * @return + */ + public List getActions() { + return (actions == null) ? null : new ArrayList(actions); + } + + /** + * Set the actions list for this flow + * If a list is already present, it will be + * replaced with the passed one. During + * addition, only the valid actions will be added + * It is a no op if the passed actions is null + * An empty actions is a vlaid input + * + * @param actions + */ + public void setActions(List actions) { + if (actions == null) { + return; + } + + this.actions = new ArrayList(actions.size()); + for (Action action : actions) { + if (action.isValid()) { + this.actions.add(action); + } + } + } + + /** + * Returns whether the Flow is for IPv4 or IPv6 + * Information is derived from match and actions list + * + * @return + */ + public boolean isIPv6() { + return (match.isIPv6()) ? true : actionsAreIPv6(); + } + + /** + * Returns true if it finds at least one action which is for IPv6 + * in the list of actions for this Flow + * + * @return + */ + private boolean actionsAreIPv6() { + if (this.actions != null) { + for (Action action : actions) { + switch (action.getType()) { + case SET_NW_SRC: + if (((SetNwSrc) action).getAddress() instanceof Inet6Address) { + return true; + } + break; + case SET_NW_DST: + if (((SetNwDst) action).getAddress() instanceof Inet6Address) { + return true; + } + break; + case SET_DL_TYPE: + if (((SetDlType) action).getDlType() == EtherTypes.IPv6 + .intValue()) { + return true; + } + break; + default: + } + } + } + return false; + } + + @Override + public Flow clone() { + Flow cloned = null; + try { + cloned = (Flow) super.clone(); + cloned.match = this.getMatch(); + cloned.actions = this.getActions(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + return cloned; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Flow[match = " + match + ", actions = " + actions + + ", priority = " + priority + ", id = " + id + + ", idleTimeout = " + idleTimeout + ", hardTimeout = " + + hardTimeout + "]"; + } + + public short getPriority() { + return priority; + } + + public void setPriority(short priority) { + this.priority = priority; + } + + public short getIdleTimeout() { + return idleTimeout; + } + + public void setIdleTimeout(short idleTimeout) { + this.idleTimeout = idleTimeout; + } + + public short getHardTimeout() { + return hardTimeout; + } + + public void setHardTimeout(short hardTimeout) { + this.hardTimeout = hardTimeout; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + /** + * Adds the specified action to the list of action of this flow + * + * @param action + * @return false if the passed action is null or not valid or if it fails to add it + */ + public boolean addAction(Action action) { + if (action == null || !action.isValid()) { + return false; + } + return actions.add(action); + } + + public boolean removeAction(Action action) { + if (action == null) { + return false; + } + return actions.remove(action); + } + + /** + * remove ALL actions of type actionType from the list of actions of this flow + * + * @param actionType + * @return false if an action of that type is present and it fails to remove it + */ + public boolean removeAction(ActionType actionType) { + Iterator actionIter = this.getActions().iterator(); + while (actionIter.hasNext()) { + Action action = actionIter.next(); + if (action.getType() == actionType) { + if (!this.removeAction(action)) + return false; + } + } + return true; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java new file mode 100644 index 0000000000..956942c09c --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerService.java @@ -0,0 +1,50 @@ + +/* + * 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.controller.sal.flowprogrammer; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.utils.Status; + +/** + * Interface for installing/removing flows on a network node + * + * + * + */ +public interface IFlowProgrammerService { + /** + * Add a flow to the network node + * + * @param node + * @param flow + */ + Status addFlow(Node node, Flow flow); + + /** + * Modify existing flow on the switch + * + * @param node + * @param flow + */ + Status modifyFlow(Node node, Flow oldflow, Flow newFlow); + + /** + * Remove the flow from the network node + * @param node + * @param flow + */ + Status removeFlow(Node node, Flow flow); + + /** + * Remove all flows present on the network node + * @param node + */ + Status removeAllFlows(Node node); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IPluginInFlowProgrammerService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IPluginInFlowProgrammerService.java new file mode 100644 index 0000000000..1fb99e0ab9 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IPluginInFlowProgrammerService.java @@ -0,0 +1,52 @@ + +/* + * 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.controller.sal.flowprogrammer; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.utils.Status; + +/** + * @file IPluginOutFlowProgrammer.java + * + * @brief Flow programmer interface to be implemented by protocol plugins + * + * + * + */ +public interface IPluginInFlowProgrammerService { + /** + * Add a flow to the network node + * + * @param node + * @param flow + */ + Status addFlow(Node node, Flow flow); + + /** + * Modify existing flow on the switch + * + * @param node + * @param flow + */ + Status modifyFlow(Node node, Flow oldFlow, Flow newFlow); + + /** + * Remove the flow from the network node + * @param node + * @param flow + */ + Status removeFlow(Node node, Flow flow); + + /** + * Remove all flows present on the network node + * @param node + */ + Status removeAllFlows(Node node); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IInventoryService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IInventoryService.java new file mode 100644 index 0000000000..2df6053098 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IInventoryService.java @@ -0,0 +1,37 @@ + +/* + * 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.controller.sal.inventory; + +import java.util.Map; +import java.util.concurrent.ConcurrentMap; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Property; + +/** + * Interface class that describes methods invoked from application toward SAL to + * solicit existing inventory data + */ +public interface IInventoryService { + /** + * The method retrieves all the existing nodes and properties attached + * + * @return map of {@link org.opendaylight.controller.sal.core.Node} and {@link org.opendaylight.controller.sal.core.Property} + */ + public ConcurrentMap> getNodeProps(); + + /** + * The method retrieve all the existing nodeConnectors and their properties + * + * @return map of {@link org.opendaylight.controller.sal.core.NodeConnector} and {@link org.opendaylight.controller.sal.core.Property} + */ + public ConcurrentMap> getNodeConnectorProps(); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IListenInventoryUpdates.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IListenInventoryUpdates.java new file mode 100644 index 0000000000..7dbb5933b4 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IListenInventoryUpdates.java @@ -0,0 +1,46 @@ + +/* + * 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.controller.sal.inventory; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Property; +import org.opendaylight.controller.sal.core.UpdateType; + +/** + * The interface class provides the methods to notify the upper applications + * in regards to any inventory changes. + */ +public interface IListenInventoryUpdates { + /** + * This method is called when some properties of a node are added/deleted/changed. + * + * @param node {@link org.opendaylight.controller.sal.core.Node} being updated + * @param type {@link org.opendaylight.controller.sal.core.UpdateType} + * @param props set of {@link org.opendaylight.controller.sal.core.Property} such as + * {@link org.opendaylight.controller.sal.core.Name} and/or + * {@link org.opendaylight.controller.sal.core.Tier} etc. + */ + public void updateNode(Node node, UpdateType type, Set props); + + /** + * This method is called when some properties of a node connector are added/deleted/changed. + * + * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} being updated + * @param type {@link org.opendaylight.controller.sal.core.UpdateType} + * @param props set of {@link org.opendaylight.controller.sal.core.Property} such as + * {@link org.opendaylight.controller.sal.core.Name} and/or + * {@link org.opendaylight.controller.sal.core.State} etc. + */ + public void updateNodeConnector(NodeConnector nodeConnector, + UpdateType type, Set props); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginInInventoryService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginInInventoryService.java new file mode 100644 index 0000000000..420f9bb00c --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginInInventoryService.java @@ -0,0 +1,39 @@ + +/* + * 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.controller.sal.inventory; + +import java.util.Map; +import java.util.concurrent.ConcurrentMap; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Property; + +/** + * The interface class that describes methods invoked from SAL toward the protocol + * plugin to solicit existing inventory data. + */ +public interface IPluginInInventoryService { + /** + * The method retrieves all the existing nodes and properties attached + * + * @return map of {@link org.opendaylight.controller.sal.core.Node} and {@link org.opendaylight.controller.sal.core.Property} + */ + public ConcurrentMap> getNodeProps(); + + /** + * The method retrieve all the existing nodeConnectors and their properties + * + * @param refresh true if it needs to solicit Openflow core; otherwise, retrieve from local cache. + * @return map of {@link org.opendaylight.controller.sal.core.NodeConnector} and {@link org.opendaylight.controller.sal.core.Property} + */ + public ConcurrentMap> getNodeConnectorProps( + Boolean refresh); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginOutInventoryService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginOutInventoryService.java new file mode 100644 index 0000000000..6fb9283755 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/inventory/IPluginOutInventoryService.java @@ -0,0 +1,46 @@ + +/* + * 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.controller.sal.inventory; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Property; +import org.opendaylight.controller.sal.core.UpdateType; + +/** + * The interface class describes Inventory update methods to be implemented by + * protocol plugin + */ +public interface IPluginOutInventoryService { + /** + * This method is called when some properties of a node are added/deleted/changed. + * + * @param node {@link org.opendaylight.controller.sal.core.Node} being updated + * @param type {@link org.opendaylight.controller.sal.core.UpdateType} + * @param props set of {@link org.opendaylight.controller.sal.core.Property} such as + * {@link org.opendaylight.controller.sal.core.Name} and/or + * {@link org.opendaylight.controller.sal.core.Tier} etc. + */ + public void updateNode(Node node, UpdateType type, Set props); + + /** + * This method is called when some properties of a node connector are added/deleted/changed. + * + * @param nodeConnector {@link org.opendaylight.controller.sal.core.NodeConnector} being updated + * @param type {@link org.opendaylight.controller.sal.core.UpdateType} + * @param props set of {@link org.opendaylight.controller.sal.core.Property} such as + * {@link org.opendaylight.controller.sal.core.Name} and/or + * {@link org.opendaylight.controller.sal.core.State} etc. + */ + public void updateNodeConnector(NodeConnector nodeConnector, + UpdateType type, Set props); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java new file mode 100644 index 0000000000..a4fc2e9ff7 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java @@ -0,0 +1,343 @@ + +/* + * 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.controller.sal.match; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.IPProtocols; +import org.opendaylight.controller.sal.utils.NetUtils; + +/** + * Represents the generic match criteria for a network frame/packet/message + * It contains a collection of individual field match + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class Match implements Cloneable { + private static final Map reversableMatches; + static { + Map map = new HashMap(); + map.put(MatchType.DL_SRC, MatchType.DL_DST); + map.put(MatchType.DL_DST, MatchType.DL_SRC); + map.put(MatchType.NW_SRC, MatchType.NW_DST); + map.put(MatchType.NW_DST, MatchType.NW_SRC); + map.put(MatchType.TP_SRC, MatchType.TP_DST); + map.put(MatchType.TP_DST, MatchType.TP_SRC); + reversableMatches = Collections.unmodifiableMap(map); + } + private Map fields; + private int matches; // concise way to tell which fields the match is set for (may remove if not needed) + + public Match() { + fields = new HashMap(); + matches = 0; + } + + public Match(Match match) { + fields = new HashMap(match.fields); + matches = match.matches; + } + + /** + * Generic setter for frame/packet/message's header fields against which to match + * Note: For MAC addresses, please pass the cloned value to this function + * + * @param type packet's header field type + * @param value field's value to assign to the match + * @param mask field's bitmask to apply to the match (has to be of the same class type of value) + */ + public void setField(MatchType type, Object value, Object mask) { + MatchField field = new MatchField(type, value, mask); + if (field.isValid()) { + fields.put(type, field); + matches |= type.getIndex(); + } + } + + /** + * Generic setter for frame/packet/message's header fields against which to match + * Note: For MAC addresses, please pass the cloned value to this function + * + * @param type packet's header field type + * @param value field's value to assign to the match + */ + public void setField(MatchType type, Object value) { + MatchField field = new MatchField(type, value); + if (field.isValid()) { + fields.put(type, field); + matches |= type.getIndex(); + } + } + + /** + * Generic setter for frame/packet/message's header field against which to match + * + * @param field the fields parameters as MAtchField object + */ + public void setField(MatchField field) { + if (field.isValid()) { + fields.put(field.getType(), field); + matches |= field.getType().getIndex(); + } + } + + /** + * Generic method to clear a field from the match + */ + public void clearField(MatchType type) { + fields.remove(type); + matches &= ~type.getIndex(); + } + + /** + * Generic getter for fields against which the match is programmed + * + * @param type frame/packet/message's header field type + * @return + */ + public MatchField getField(MatchType type) { + return fields.get(type); + } + + /** + * Returns the fields the match is set for in a bitmask fashion + * Each bit represents a field the match is configured for + * + * @return the 32 bit long mask (Refer to {@code}org.opendaylight.controller.sal.match.MatchElement) + */ + @XmlElement + public int getMatches() { + return matches; + } + + /** + * Returns the list of MatchType fields the match is set for + * + * @return List of individual MatchType fields. + */ + public List getMatchesList() { + return new ArrayList(fields.keySet()); + } + + /** + * Returns whether this match is for an IPv6 flow + */ + public boolean isIPv6() { + return (isPresent(MatchType.DL_TYPE) + && ((Short) getField(MatchType.DL_TYPE).getValue()) + .equals(EtherTypes.IPv6.shortValue()) + || isPresent(MatchType.NW_PROTO) + && ((Byte) getField(MatchType.NW_PROTO).getValue()) + .equals(IPProtocols.IPV6ICMP.byteValue()) + || isPresent(MatchType.NW_SRC) + && getField(MatchType.NW_SRC).getValue() instanceof Inet6Address || isPresent(MatchType.NW_DST) + && getField(MatchType.NW_DST).getValue() instanceof Inet6Address); + } + + /** + * Returns whether this match is for an IPv4 flow + */ + public boolean isIPv4() { + return !isIPv6(); + } + + /** + * Returns whether for the specified field type the match is to be considered "any" + * Equivalent to say this match does not care about the value of the specified field + * + * @param type + * @return + */ + public boolean isAny(MatchType type) { + //return ((fields.get(type) == null) || (fields.get(type).getBitMask() == 0L)); + return !fields.containsKey(type); + } + + /** + * Returns whether a match for the specified field type is configured + * + * @param type + * @return + */ + public boolean isPresent(MatchType type) { + return (fields.get(type) != null); + } + + @Override + public Match clone() { + Match cloned = null; + try { + cloned = (Match) super.clone(); + cloned.fields = new HashMap(); + for (Entry entry : this.fields.entrySet()) { + cloned.fields.put(entry.getKey(), entry.getValue().clone()); + } + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + return cloned; + } + + /** + * Returns a reversed version of this match + * For example, in the reversed version the network source and destination + * addresses will be exchanged. Non symmetric match field will not be + * copied over into the reversed match version, like input port. + * + * @return + */ + public Match reverse() { + // Copy over all fields + Match reverse = this.clone(); + + // Flip symmetric fields + for (Map.Entry entry : Match.reversableMatches + .entrySet()) { + MatchType from = entry.getKey(); + MatchType to = entry.getValue(); + if (this.isPresent(from)) { + reverse.setField(to, this.getField(from).getValue(), this + .getField(from).getMask()); + } + } + + // Reset asymmetric fields + reverse.clearField(MatchType.IN_PORT); + + return reverse; + } + + /** + * Check whether the current match conflicts with the passed filter match + * This match conflicts with the filter if for at least a MatchType defined + * in the filter match, the respective MatchFields differ or are not compatible + * + * For example, Let's suppose the filter has the following MatchFields: + * DL_TYPE = 0x800 + * NW_DST = 172.20.30.110/24 + * + * while this match has the following MatchFields: + * NW_DST = 172.20.30.45/24 + * TP_DST = 80 + * + * Then the function would return false as the two Match are not conflicting + * + * Note: the mask value is taken into account only for MatchType.NW_SRC and MatchType.NW_DST + * + * @param match the MAtch describing the filter + * @return true if the match is conflicting with the filter, false otherwise + */ + public boolean conflictWithFilter(Match filter) { + // Iterate through the MatchType defined in the filter + for (MatchType type : filter.getMatchesList()) { + if (this.isAny(type)) { + continue; + } + + MatchField thisField = this.getField(type); + MatchField filterField = filter.getField(type); + + switch (type) { + case DL_SRC: + case DL_DST: + if (Arrays.equals((byte[]) thisField.getValue(), + (byte[]) filterField.getValue())) { + return false; + } + break; + case NW_SRC: + case NW_DST: + InetAddress thisAddress = (InetAddress) thisField.getValue(); + InetAddress filterAddress = (InetAddress) filterField + .getValue(); + // Validity check + if (thisAddress instanceof Inet4Address + && filterAddress instanceof Inet6Address + || thisAddress instanceof Inet6Address + && filterAddress instanceof Inet4Address) { + return true; + } + InetAddress thisMask = (InetAddress) filter.getField(type) + .getMask(); + InetAddress filterMask = (InetAddress) filter.getField(type) + .getMask(); + // thisAddress has to be in same subnet of filterAddress + if (NetUtils.inetAddressConflict(thisAddress, filterAddress, + thisMask, filterMask)) { + return true; + } + break; + default: + if (!thisField.getValue().equals(filterField.getValue())) { + return true; + } + } + //TODO: check v4 v6 incompatibility + } + return false; + } + + /** + * Merge the current Match fields with the fields of the filter Match + * A check is first run to see if this Match is compatible with the + * filter Match. If it is not, the merge is not attempted. + * + * + * @param filter + * @return + */ + public Match mergeWithFilter(Match filter) { + if (!this.conflictWithFilter(filter)) { + /* + * No conflict with the filter + * We can copy over the fields which this match does not have + */ + for (MatchType type : filter.getMatchesList()) { + if (this.isAny(type)) { + this.setField(filter.getField(type).clone()); + } + } + } + return this; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "Match[" + fields.values() + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java new file mode 100644 index 0000000000..19c365b29e --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java @@ -0,0 +1,186 @@ + +/* + * 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.controller.sal.match; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.utils.HexEncode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Represents the generic matching field + * + * + * + */ +public class MatchField implements Cloneable { + private static final Logger logger = LoggerFactory + .getLogger(MatchField.class); + private MatchType type; // the field we want to match + private Object value; // the value of the field we want to match + private Object mask; // the value of the mask we want to match on the specified field + private transient boolean isValid; + + /** + * Mask based match constructor + * + * @param type + * @param value + * @param mask has to be of the same class type of value. A null mask means full match + */ + public MatchField(MatchType type, Object value, Object mask) { + this.type = type; + this.value = value; + this.mask = mask; + this.isValid = checkValueType() && checkValues(); // Keep this logic, value checked only if type check is fine + } + + /** + * Full match constructor + * + * @param type + * @param value + */ + public MatchField(MatchType type, Object value) { + this.type = type; + this.value = value; + this.mask = null; + this.isValid = checkValueType() && checkValues(); // Keep this logic, value checked only if type check is fine + } + + /** + * Returns the value set for this match field + * + * @return + */ + public Object getValue() { + return value; + } + + /** + * Returns the type field this match field object is for + * + * @return + */ + public MatchType getType() { + return type; + } + + /** + * Returns the mask value set for this field match + * A null mask means this is a full match + * @return + */ + public Object getMask() { + return mask; + } + + /** + * Returns the bitmask set for this field match + * + * @return + */ + public long getBitMask() { + return type.getBitMask(mask); + } + + /** + * Returns whether the field match configuration is valid or not + * + * @return + */ + public boolean isValid() { + return isValid; + } + + private boolean checkValueType() { + if (type.isCongruentType(value, mask) == false) { + String valueClass = (value == null) ? "null" : value.getClass() + .getSimpleName(); + String maskClass = (mask == null) ? "null" : mask.getClass() + .getSimpleName(); + String error = "Invalid match field's value or mask types.For field: " + + type.id() + + " Expected:" + + type.dataType().getSimpleName() + + " or equivalent," + + " Got:(" + valueClass + "," + maskClass + ")"; + throwException(error); + return false; + } + return true; + } + + private boolean checkValues() { + if (type.isValid(value, mask) == false) { + String maskString = (mask == null) ? "null" : ("0x" + Integer + .toHexString(Integer.parseInt(mask.toString()))); + String error = "Invalid match field's value or mask assignement.For field: " + + type.id() + + " Expected: " + + type.getRange() + + ", Got:(0x" + + Integer.toHexString(Integer.parseInt(value.toString())) + + "," + maskString + ")"; + + throwException(error); + return false; + } + return true; + } + + private static void throwException(String error) { + try { + throw new Exception(error); + } catch (Exception e) { + logger.error(e.getMessage()); + } + } + + @Override + public MatchField clone() { + MatchField cloned = null; + try { + cloned = (MatchField) super.clone(); + if (value instanceof byte[]) { + cloned.value = ((byte[]) this.value).clone(); + if (this.mask != null) { + cloned.mask = ((byte[]) this.mask).clone(); + } + } + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + return cloned; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + String valueString = (value == null) ? "null" + : (value instanceof byte[]) ? HexEncode + .bytesToHexString((byte[]) value) : value.toString(); + String maskString = (mask == null) ? "null" + : (mask instanceof byte[]) ? HexEncode + .bytesToHexString((byte[]) mask) : mask.toString(); + + return type + "(" + valueString + "," + maskString + ")"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchType.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchType.java new file mode 100644 index 0000000000..b54dd3bcd2 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchType.java @@ -0,0 +1,193 @@ + +/* + * 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.controller.sal.match; + +import java.net.InetAddress; + +import org.opendaylight.controller.sal.core.NodeConnector; + +/** + * Represents the binding between the id, the value and mask type and the range values + * of the elements type that can be matched on the network frame/packet/message + * + * + * + */ +public enum MatchType { + IN_PORT("inPort", 1 << 0, NodeConnector.class, 1, 0), DL_SRC("dlSrc", + 1 << 1, Byte[].class, 0, 0xffffffffffffL), DL_DST("dlDst", 1 << 2, + Byte[].class, 0, 0xffffffffffffL), DL_VLAN("dlVlan", 1 << 3, + Short.class, 2, 0xfff), // 2 bytes + DL_VLAN_PR("dlVlanPriority", 1 << 4, Byte.class, 0, 0x7), // 3 bits + DL_OUTER_VLAN("dlOuterVlan", 1 << 5, Short.class, 2, 0xfff), DL_OUTER_VLAN_PR( + "dlOuterVlanPriority", 1 << 6, Short.class, 0, 0x7), DL_TYPE( + "dlType", 1 << 7, Short.class, 0, 0xffff), // 2 bytes + NW_TOS("nwTOS", 1 << 8, Byte.class, 0, 0xff), // 1 byte + NW_PROTO("nwProto", 1 << 9, Byte.class, 0, 0xff), // 1 byte + NW_SRC("nwSrc", 1 << 10, InetAddress.class, 0, 0), NW_DST("nwDst", 1 << 11, + InetAddress.class, 0, 0), TP_SRC("tpSrc", 1 << 12, Short.class, 1, + 0xffff), // 2 bytes + TP_DST("tpDst", 1 << 13, Short.class, 1, 0xffff); // 2 bytes + + private String id; + private int index; + private Class dataType; + private long minValue; + private long maxValue; + + private MatchType(String id, int index, Class dataType, long minValue, + long maxValue) { + this.id = id; + this.index = index; + this.dataType = dataType; + this.minValue = minValue; + this.maxValue = maxValue; + } + + public String id() { + return id; + } + + public int getIndex() { + return index; + } + + public Class dataType() { + return dataType; + } + + public String getRange() { + return "[0x" + Long.toHexString(minValue) + "-0x" + + Long.toHexString(maxValue) + "]"; + } + + /** + * Perform the assignment type validation + * @param value + * @param mask + * @return + */ + public boolean isCongruentType(Object value, Object mask) { + // Mask type has to match value type + if (mask != null && (mask.getClass() != value.getClass())) { + return false; + } + + Class e = this.dataType(); + Class g = value.getClass(); + + // This is all what we need, if value type is same of match required type + if (g.equals(e)) { + return true; + } + + // This is for the numeric class vs primitive congruence + // For what concerns here, for instance, Integer is congruent to int + if (e == Short.class) { + return g.equals(short.class); + } + + if (e == Integer.class) { + return g.equals(int.class); + } + + if (e == Byte.class) { + return g.equals(byte.class); + } + + if (e == Byte[].class) { + return g.equals(byte[].class); + } + + if (e == InetAddress.class) { + return g.getSuperclass().equals(InetAddress.class); + } + return false; + } + + /** + * Perform the value and mask range validation + * @param value + * @param mask + * @return + */ + public boolean isValid(Object value, Object mask) { + // Skip if main error + if (mask != null && (mask.getClass() != value.getClass())) { + return false; + } + // For the complex below types let's skip the value range check for now + if (this.dataType == InetAddress.class) { + return true; + } + if (this.dataType() == Byte[].class) { + return true; + } + if (this.dataType() == NodeConnector.class) { + return true; + } + + int val = 0; + int msk = 0; + if (value.getClass() == Integer.class || value.getClass() == int.class) { + val = ((Integer) value).intValue(); + msk = (mask != null) ? ((Integer) mask).intValue() : 0; + + } else if (value.getClass() == Short.class + || value.getClass() == short.class) { + val = ((Short) value).intValue() & 0xffff; + msk = (mask != null) ? ((Short) mask).intValue() & 0xffff : 0; + + } else if (value.getClass() == Byte.class + || value.getClass() == byte.class) { + val = ((Byte) value).intValue() & 0xff; + msk = (mask != null) ? ((Byte) mask).intValue() & 0xff : 0; + } + return ((val >= minValue && val <= maxValue) && (mask == null || (msk >= minValue && msk <= maxValue))); + + } + + /** + * Return the mask value in 64 bits bitmask form + * @param mask + * @return + */ + public long getBitMask(Object mask) { + if (this.dataType == InetAddress.class) { + //TODO handle Inet v4 and v6 v6 will have a second upper mask + return 0; + } + if (this.dataType() == Byte[].class) { + if (mask == null) { + return 0xffffffffffffL; + } + byte mac[] = (byte[]) mask; + long bitmask = 0; + for (short i = 0; i < 6; i++) { + // bitmask |= (((long)mac[i] & 0xffL) << (long)((5-i)*8)); + bitmask |= (((long) mac[i] & 0xffL) << ((5 - i) * 8)); + } + return bitmask; + } + if (this.dataType == Integer.class || this.dataType == int.class) { + return (mask == null) ? this.maxValue : ((Integer) mask) + .longValue(); + + } + if (this.dataType == Short.class || this.dataType == short.class) { + return (mask == null) ? this.maxValue : ((Short) mask).longValue(); + } + if (this.dataType == Byte.class || this.dataType == byte.class) { + return (mask == null) ? this.maxValue : ((Byte) mask).longValue(); + + } + return 0L; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ARP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ARP.java new file mode 100644 index 0000000000..f3aa35f637 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ARP.java @@ -0,0 +1,259 @@ + +/* + * 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.controller.sal.packet; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +/** + * Class that represents the ARP packet objects + * + * + */ + +public class ARP extends Packet { + private static final String HWTYPE = "HardwareType"; + private static final String PTYPE = "ProtocolType"; + private static final String HWADDRLENGTH = "HardwareAddressLength"; + private static final String PADDRLENGTH = "ProtocolAddressLength"; + private static final String OPCODE = "OpCode"; + private static final String SENDERHWADDR = "SenderHardwareAddress"; + private static final String SENDERPADDR = "SenderProtocolAddress"; + private static final String TARGETHWADDR = "TargetHardwareAddress"; + private static final String TARGETPADDR = "TargetProtocolAddress"; + + public static short HW_TYPE_ETHERNET = (short) 0x1; + public static short REQUEST = (short) 0x1; + public static short REPLY = (short) 0x2; + + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + { + put(HWTYPE, new ImmutablePair(0, 16)); + put(PTYPE, new ImmutablePair(16, 16)); + put(HWADDRLENGTH, new ImmutablePair(32, 8)); + put(PADDRLENGTH, new ImmutablePair(40, 8)); + put(OPCODE, new ImmutablePair(48, 16)); + put(SENDERHWADDR, new ImmutablePair(64, 48)); + put(SENDERPADDR, new ImmutablePair(112, 32)); + put(TARGETHWADDR, new ImmutablePair(144, 48)); + put(TARGETPADDR, new ImmutablePair(192, 32)); + + } + }; + private Map fieldValues; + + /** + * Default constructor that creates and sets the HashMap + */ + public ARP() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + /** + * Constructor that sets the access level for the packet and + * creates and sets the HashMap + */ + public ARP(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + /** + * Gets the hardware type from the stored ARP header + * @return short - the hardwareType + */ + public short getHardwareType() { + return (BitBufferHelper.getShort(fieldValues.get(HWTYPE))); + + } + + /** + * Gets the protocol type from the stored ARP header + * @return short - the protocolType + */ + public short getProtocolType() { + return (BitBufferHelper.getShort(fieldValues.get(PTYPE))); + } + + /** + * Gets the hardware address length from the stored ARP header + * @return byte - the protocolAddressLength + */ + public byte getHardwareAddressLength() { + return (BitBufferHelper.getByte(fieldValues.get(HWADDRLENGTH))); + } + + /** + * Get the protocol address length from Protocol header + * @return byte - the protocolAddressLength + */ + public byte getProtocolAddressLength() { + return (BitBufferHelper.getByte(fieldValues.get(PADDRLENGTH))); + } + + /** + * Gets the opCode from stored ARP header + * @param short - the opCode to set + */ + public short getOpCode() { + return (BitBufferHelper.getShort(fieldValues.get(OPCODE))); + } + + /** + * Gets the sender hardware address from the stored ARP header + * @return byte[] - the senderHardwareAddress + */ + public byte[] getSenderHardwareAddress() { + return (fieldValues.get(SENDERHWADDR)); + } + + /** + * Gets the IP address from the stored ARP header + * @return byte[] - the senderProtocolAddress + */ + public byte[] getSenderProtocolAddress() { + return (fieldValues.get(SENDERPADDR)); + } + + /** + * Gets the hardware address from the stored ARP header + * @return byte[] - the targetHardwareAddress + */ + public byte[] getTargetHardwareAddress() { + return (fieldValues.get(TARGETHWADDR)); + } + + /** + * Sets the hardware Type for the current ARP object instance + * @param short - hardwareType the hardwareType to set + * @return ARP + */ + public ARP setHardwareType(short hardwareType) { + byte[] hwType = BitBufferHelper.toByteArray(hardwareType); + fieldValues.put(HWTYPE, hwType); + return this; + } + + /** + * Sets the protocol Type for the current ARP object instance + * @param short - the protocolType to set + * @return ARP + */ + public ARP setProtocolType(short protocolType) { + byte[] protType = BitBufferHelper.toByteArray(protocolType); + fieldValues.put(PTYPE, protType); + return this; + } + + /** + * Sets the hardware address length for the current ARP object instance + * @param byte - the hardwareAddressLength to set + * @return ARP + */ + public ARP setHardwareAddressLength(byte hardwareAddressLength) { + byte[] hwAddressLength = BitBufferHelper + .toByteArray(hardwareAddressLength); + fieldValues.put(HWADDRLENGTH, hwAddressLength); + return this; + } + + /** + * Sets the Protocol address for the current ARP object instance + * @param byte - the protocolAddressLength to set + * @return ARP + */ + public ARP setProtocolAddressLength(byte protocolAddressLength) { + byte[] protocolAddrLength = BitBufferHelper + .toByteArray(protocolAddressLength); + fieldValues.put(PADDRLENGTH, protocolAddrLength); + return this; + } + + /** + * Sets the opCode for the current ARP object instance + * @param short - the opCode to set + * @return ARP + */ + public ARP setOpCode(short opCode) { + byte[] operationCode = BitBufferHelper.toByteArray(opCode); + fieldValues.put(OPCODE, operationCode); + return this; + } + + /** + * Sets the sender hardware address for the current ARP object instance + * @param byte[] - the senderHardwareAddress to set + * @return ARP + */ + public ARP setSenderHardwareAddress(byte[] senderHardwareAddress) { + fieldValues.put(SENDERHWADDR, senderHardwareAddress); + return this; + } + + /** + * Sets the target hardware address for the current ARP object instance + * @param byte[] - the targetHardwareAddress to set + * @return ARP + */ + public ARP setTargetHardwareAddress(byte[] targetHardwareAddress) { + fieldValues.put(TARGETHWADDR, targetHardwareAddress); + return this; + } + + /** + * Sets the target protocol address for the current ARP object instance + * @param byte[] - the targetProtocolAddress to set + * @return ARP + */ + public ARP setTargetProtocolAddress(byte[] targetProtocolAddress) { + fieldValues.put(TARGETPADDR, targetProtocolAddress); + return this; + } + + /** + * Sets the sender protocol address for the current ARP object instance + * @param byte[] - senderIP + * @return ARP + */ + public ARP setSenderProtocolAddress(byte[] senderIP) { + fieldValues.put(SENDERPADDR, senderIP); + return this; + } + + /** + * Gets the target protocol address + * @return - byte[] targetProtocolAddress + */ + public byte[] getTargetProtocolAddress() { + return fieldValues.get(TARGETPADDR); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/BitBufferHelper.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/BitBufferHelper.java new file mode 100644 index 0000000000..1c27292117 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/BitBufferHelper.java @@ -0,0 +1,685 @@ + +/* + * 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.controller.sal.packet; + +import java.util.Arrays; + +import org.opendaylight.controller.sal.utils.NetUtils; + +/** + * BitBufferHelper class that provides utility methods to + * - fetch specific bits from a serialized stream of bits + * - convert bits to primitive data type - like short, int, long + * - store bits in specified location in stream of bits + * - convert primitive data types to stream of bits + * + * + */ +public abstract class BitBufferHelper { + + public static long ByteMask = 0xFF; + + // Getters + // data: array where data are stored + // startOffset: bit from where to start reading + // numBits: number of bits to read + // All this function return an exception if overflow or underflow + + /** + * Returns the first byte from the byte array + * @param byte[] data + * @return byte value + */ + public static byte getByte(byte[] data) { + if ((data.length * NetUtils.NumBitsInAByte) > Byte.SIZE) { + try { + throw new Exception( + "Container is too small for the number of requested bits"); + } catch (Exception e) { + e.printStackTrace(); + } + } + return (data[0]); + } + + /** + * Returns the short value for the byte array passed. + * Size of byte array is restricted to Short.SIZE + * @param byte[] data + * @return short value + */ + public static short getShort(byte[] data) { + if (data.length > Short.SIZE) { + try { + throw new Exception( + "Container is too small for the number of requested bits"); + } catch (Exception e) { + e.printStackTrace(); + } + } + return (short) toNumber(data); + } + + /** + * Returns the int value for the byte array passed. + * Size of byte array is restricted to Integer.SIZE + * @param byte[] data + * @return int - the integer value of byte array + */ + public static int getInt(byte[] data) { + if (data.length > Integer.SIZE) { + try { + throw new Exception( + "Container is too small for the number of requested bits"); + } catch (Exception e) { + e.printStackTrace(); + } + } + return (int) toNumber(data); + } + + /** + * Returns the long value for the byte array passed. + * Size of byte array is restricted to Long.SIZE + * @param byte[] data + * @return long - the integer value of byte array + */ + public static long getLong(byte[] data) { + if (data.length > Long.SIZE) { + try { + throw new Exception( + "Container is too small for the number of requested bits"); + } catch (Exception e) { + e.printStackTrace(); + } + } + return (long) toNumber(data); + } + + /** + * Returns the short value for the last numBits of the byte array passed. + * Size of numBits is restricted to Short.SIZE + * @param byte[] data + * @param int - numBits + * @return short - the short value of byte array + * @throws Exception + */ + public static short getShort(byte[] data, int numBits) throws Exception { + if (numBits > Short.SIZE) { + try { + throw new Exception( + "Container is too small for the number of requested bits"); + } catch (Exception e) { + e.printStackTrace(); + } + } + int startOffset = data.length * NetUtils.NumBitsInAByte - numBits; + return (short) toNumber(BitBufferHelper.getBits(data, startOffset, + numBits), numBits); + } + + /** + * Returns the int value for the last numBits of the byte array passed. + * Size of numBits is restricted to Integer.SIZE + * @param byte[] data + * @param int - numBits + * @return int - the integer value of byte array + * @throws Exception + */ + public static int getInt(byte[] data, int numBits) throws Exception { + if (numBits > Integer.SIZE) { + try { + throw new Exception( + "Container is too small for the number of requiested bits"); + } catch (Exception e) { + e.printStackTrace(); + } + } + int startOffset = data.length * NetUtils.NumBitsInAByte - numBits; + return (int) toNumber(BitBufferHelper.getBits(data, startOffset, + numBits), numBits); + } + + /** + * Returns the long value for the last numBits of the byte array passed. + * Size of numBits is restricted to Long.SIZE + * @param byte[] data + * @param int - numBits + * @return long - the integer value of byte array + * @throws Exception + */ + + public static long getLong(byte[] data, int numBits) throws Exception { + if (numBits > Long.SIZE) { + try { + throw new Exception( + "Container is too small for the number of requested bits"); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (numBits > data.length * NetUtils.NumBitsInAByte) { + try { + throw new Exception( + "Trying to read more bits than contained in the data buffer"); + } catch (Exception e) { + e.printStackTrace(); + } + } + int startOffset = data.length * NetUtils.NumBitsInAByte - numBits; + return toNumber(BitBufferHelper.getBits(data, startOffset, numBits), + numBits); + } + + /** + * Reads the specified number of bits from the passed byte array + * starting to read from the specified offset + * The bits read are stored in a byte array which size is dictated + * by the number of bits to be stored. + * The bits are stored in the byte array LSB aligned. + * + * Ex. + * Read 7 bits at offset 10 + * 0 9 10 16 17 + * 0101000010 | 0000101 | 1111001010010101011 + * will be returned as {0,0,0,0,0,1,0,1} + * + * @param byte[] data + * @param int startOffset - offset to start fetching bits from data from + * @param int numBits - number of bits to be fetched from data + * @return byte [] - LSB aligned bits + * @throws Exception + */ + public static byte[] getBits(byte[] data, int startOffset, int numBits) + throws Exception { + + int startByteOffset = 0; + int valfromcurr, valfromnext; + int extranumBits = numBits % NetUtils.NumBitsInAByte; + int extraOffsetBits = startOffset % NetUtils.NumBitsInAByte; + int numBytes = (numBits % NetUtils.NumBitsInAByte != 0) ? 1 + numBits + / NetUtils.NumBitsInAByte : numBits / NetUtils.NumBitsInAByte; + byte[] shiftedBytes = new byte[numBytes]; + startByteOffset = startOffset / NetUtils.NumBitsInAByte; + byte[] bytes = new byte[numBytes]; + if (numBits == 0) + return bytes; + + checkExceptions(data, startOffset, numBits); + + if (extraOffsetBits == 0) { + if (extranumBits == 0) { + System.arraycopy(data, startByteOffset, bytes, 0, numBytes); + return bytes; + } else { + System.arraycopy(data, startByteOffset, bytes, 0, numBytes - 1); + bytes[numBytes - 1] = (byte) ((int) data[startByteOffset + + numBytes - 1] & getMSBMask(extranumBits)); + } + } else { + int i; + for (i = 0; i < numBits / NetUtils.NumBitsInAByte; i++) { + // Reading Numbytes starting from offset + valfromcurr = (data[startByteOffset + i]) + & getLSBMask(NetUtils.NumBitsInAByte - extraOffsetBits); + valfromnext = (data[startByteOffset + i + 1]) + & getMSBMask(extraOffsetBits); + bytes[i] = (byte) (valfromcurr << (extraOffsetBits) | (valfromnext >> (NetUtils.NumBitsInAByte - extraOffsetBits))); + } + // Now adding the rest of the bits if any + if (extranumBits != 0) { + if (extranumBits < (NetUtils.NumBitsInAByte - extraOffsetBits)) { + valfromnext = (byte) (data[startByteOffset + i + 1] & ((getMSBMask(extranumBits)) >> extraOffsetBits)); + bytes[i] = (byte) (valfromnext << extraOffsetBits); + } else if (extranumBits == (NetUtils.NumBitsInAByte - extraOffsetBits)) { + valfromcurr = (data[startByteOffset + i]) + & getLSBMask(NetUtils.NumBitsInAByte + - extraOffsetBits); + bytes[i] = (byte) (valfromcurr << extraOffsetBits); + } else { + valfromcurr = (data[startByteOffset + i]) + & getLSBMask(NetUtils.NumBitsInAByte + - extraOffsetBits); + valfromnext = (data[startByteOffset + i + 1]) + & (getMSBMask(extranumBits + - (NetUtils.NumBitsInAByte - extraOffsetBits))); + bytes[i] = (byte) (valfromcurr << (extraOffsetBits) | (valfromnext >> (NetUtils.NumBitsInAByte - extraOffsetBits))); + } + + } + } + // Aligns the bits to LSB + shiftedBytes = shiftBitsToLSB(bytes, numBits); + return shiftedBytes; + } + + // Setters + // data: array where data will be stored + // input: the data that need to be stored in the data array + // startOffset: bit from where to start writing + // numBits: number of bits to read + + /** + * Bits are expected to be stored in the input byte array from LSB + * @param byte[] - data to set the input byte + * @param byte - input byte to be inserted + * @param startOffset - offset of data[] to start inserting byte from + * @param numBits - number of bits of input to be inserted into data[] + * @return void + * @throws Exception + */ + public static void setByte(byte[] data, byte input, int startOffset, + int numBits) throws Exception { + byte[] inputByteArray = new byte[1]; + Arrays.fill(inputByteArray, 0, 1, input); + setBytes(data, inputByteArray, startOffset, numBits); + } + + /** + * Bits are expected to be stored in the input byte array from LSB + * @param byte[] - data to set the input byte + * @param byte[] - input bytes to be inserted + * @param startOffset - offset of data[] to start inserting byte from + * @param numBits - number of bits of input to be inserted into data[] + * @return void + * @throws Exception + */ + public static void setBytes(byte[] data, byte[] input, int startOffset, + int numBits) throws Exception { + checkExceptions(data, startOffset, numBits); + insertBits(data, input, startOffset, numBits); + } + + /** + * Returns numBits 1's in the MSB position + * @param numBits + * @return + */ + public static int getMSBMask(int numBits) { + int mask = 0; + for (int i = 0; i < numBits; i++) { + mask = mask | (1 << (7 - i)); + } + return mask; + } + + /** + * Returns numBits 1's in the LSB position + * @param numBits + * @return + */ + public static int getLSBMask(int numBits) { + int mask = 0; + for (int i = 0; i < numBits; i++) { + mask = mask | (1 << i); + } + return mask; + } + + /** + * Returns the numerical value of the byte array passed + * @param byte[] - array + * @return long - numerical value of byte array passed + */ + static public long toNumber(byte[] array) { + long ret = 0; + long length = array.length; + int value = 0; + for (int i = 0; i < length; i++) { + value = array[i]; + if (value < 0) + value += 256; + ret = ret + | (long) ((long) value << ((length - i - 1) * NetUtils.NumBitsInAByte)); + } + return ret; + } + + /** + * Returns the numerical value of the last numBits (LSB bits) + * of the byte array passed + * @param byte[] - array + * @param int - numBits + * @return long - numerical value of byte array passed + */ + static public long toNumber(byte[] array, int numBits) { + int length = numBits / NetUtils.NumBitsInAByte; + int bitsRest = numBits % NetUtils.NumBitsInAByte; + int startOffset = array.length - length; + long ret = 0; + int value = 0; + + value = array[startOffset - 1] & getLSBMask(bitsRest); + value = (array[startOffset - 1] < 0) ? (array[startOffset - 1] + 256) + : array[startOffset - 1]; + ret = ret + | (value << ((array.length - startOffset) * NetUtils.NumBitsInAByte)); + + for (int i = startOffset; i < array.length; i++) { + value = array[i]; + if (value < 0) + value += 256; + ret = ret + | (long) ((long) value << ((array.length - i - 1) * NetUtils.NumBitsInAByte)); + } + + return ret; + } + + /** + * Accepts a number as input and returns its value in byte form + * in LSB aligned form + * example: input = 5000 [1001110001000] + * bytes = 19, -120 [00010011] [10001000] + * @param Number + * @return byte[] + * + */ + + public static byte[] toByteArray(Number input) { + Class dataType = input.getClass(); + short size = 0; + long Lvalue = input.longValue(); + + if (dataType == Byte.class || dataType == byte.class) + size = Byte.SIZE; + else if (dataType == Short.class || dataType == short.class) + size = Short.SIZE; + else if (dataType == Integer.class || dataType == int.class) + size = Integer.SIZE; + else if (dataType == Long.class || dataType == long.class) + size = Long.SIZE; + else + throw new IllegalArgumentException( + "Parameter must one of the following: Short/Int/Long\n"); + + int length = size / NetUtils.NumBitsInAByte; + byte bytes[] = new byte[length]; + + /*Getting the bytes from input value*/ + for (int i = 0; i < length; i++) { + bytes[i] = (byte) ((Lvalue >> (NetUtils.NumBitsInAByte * (length + - i - 1))) & ByteMask); + } + return bytes; + } + + /** + * Accepts a number as input and returns its value in byte form + * in MSB aligned form + * example: input = 5000 [1001110001000] + * bytes = -114, 64 [10011100] [01000000] + * @param Number input + * @param int numBits - the number of bits to be returned + * @return byte[] + * + */ + public static byte[] toByteArray(Number input, int numBits) { + Class dataType = input.getClass(); + short size = 0; + long Lvalue = input.longValue(); + + if (dataType == Short.class) { + size = Short.SIZE; + } else if (dataType == Integer.class) { + size = Integer.SIZE; + } else if (dataType == Long.class) { + size = Long.SIZE; + } else { + throw new IllegalArgumentException( + "Parameter must one of the following: Short/Int/Long\n"); + } + + int length = size / NetUtils.NumBitsInAByte; + byte bytes[] = new byte[length]; + byte[] inputbytes = new byte[length]; + byte shiftedBytes[]; + + //Getting the bytes from input value + for (int i = 0; i < length; i++) { + bytes[i] = (byte) ((Lvalue >> (NetUtils.NumBitsInAByte * (length + - i - 1))) & ByteMask); + } + + if ((bytes[0] == 0 && dataType == Long.class) + || (bytes[0] == 0 && dataType == Integer.class)) { + int index = 0; + for (index = 0; index < length; ++index) { + if (bytes[index] != 0) { + bytes[0] = bytes[index]; + break; + } + } + System.arraycopy(bytes, index, inputbytes, 0, length - index); + Arrays.fill(bytes, length - index + 1, length - 1, (byte) 0); + } else { + System.arraycopy(bytes, 0, inputbytes, 0, length); + } + + shiftedBytes = shiftBitsToMSB(inputbytes, numBits); + + return shiftedBytes; + } + + /** + * Takes an LSB aligned byte array and returned the LSB numBits in a MSB aligned byte array + * + * @param inputbytes + * @param numBits + * @return + */ + /** + * It aligns the last numBits bits to the head of the byte array + * following them with numBits % 8 zero bits. + * + * Example: + * For inputbytes = [00000111][01110001] and numBits = 12 it returns: + * shiftedBytes = [01110111][00010000] + * + * @param byte[] inputBytes + * @param int numBits - number of bits to be left aligned + * @return byte[] + */ + public static byte[] shiftBitsToMSB(byte[] inputBytes, int numBits) { + int numBitstoShiftBy = 0, leadZeroesMSB = 8, numEndRestBits = 0; + int size = inputBytes.length; + byte[] shiftedBytes = new byte[size]; + int i; + + for (i = 0; i < Byte.SIZE; i++) { + if (((byte) (inputBytes[0] & getMSBMask(i + 1))) != 0) { + leadZeroesMSB = i; + break; + } + } + + if (numBits % NetUtils.NumBitsInAByte == 0) + numBitstoShiftBy = 0; + else + numBitstoShiftBy = ((NetUtils.NumBitsInAByte - (numBits % NetUtils.NumBitsInAByte)) < leadZeroesMSB) ? (NetUtils.NumBitsInAByte - (numBits % NetUtils.NumBitsInAByte)) + : leadZeroesMSB; + + if (numBitstoShiftBy == 0) + return inputBytes; + + if (numBits < NetUtils.NumBitsInAByte) { //inputbytes.length = 1 OR Read less than a byte + shiftedBytes[0] = (byte) ((inputBytes[0] & getLSBMask(numBits)) << numBitstoShiftBy); + } else { + numEndRestBits = NetUtils.NumBitsInAByte + - (inputBytes.length * NetUtils.NumBitsInAByte - numBits - numBitstoShiftBy); //# of bits to read from last byte + for (i = 0; i < (size - 1); i++) { + if ((i + 1) == (size - 1)) { + if (numEndRestBits > numBitstoShiftBy) { + shiftedBytes[i] = (byte) ((inputBytes[i] << numBitstoShiftBy) | ((inputBytes[i + 1] & getMSBMask(numBitstoShiftBy)) >> (numEndRestBits - numBitstoShiftBy))); + shiftedBytes[i + 1] = (byte) ((inputBytes[i + 1] & getLSBMask(numEndRestBits + - numBitstoShiftBy)) << numBitstoShiftBy); + } else + shiftedBytes[i] = (byte) ((inputBytes[i] << numBitstoShiftBy) | ((inputBytes[i + 1] & getMSBMask(numEndRestBits)) >> (NetUtils.NumBitsInAByte - numEndRestBits))); + } + shiftedBytes[i] = (byte) ((inputBytes[i] << numBitstoShiftBy) | (inputBytes[i + 1] & getMSBMask(numBitstoShiftBy)) >> (NetUtils.NumBitsInAByte - numBitstoShiftBy)); + } + + } + return shiftedBytes; + } + + /** + * It aligns the first numBits bits to the right end of the byte array + * preceding them with numBits % 8 zero bits. + * + * Example: + * For inputbytes = [01110111][00010000] and numBits = 12 it returns: + * shiftedBytes = [00000111][01110001] + * + * @param byte[] inputBytes + * @param int numBits - number of bits to be right aligned + * @return byte[] + */ + public static byte[] shiftBitsToLSB(byte[] inputBytes, int numBits) { + int numBytes = inputBytes.length; + int numBitstoShift = numBits % NetUtils.NumBitsInAByte; + byte[] shiftedBytes = new byte[numBytes]; + int inputLsb = 0, inputMsb = 0; + + if (numBitstoShift == 0) + return inputBytes; + + for (int i = 1; i < numBytes; i++) { + inputLsb = inputBytes[i - 1] + & getLSBMask(NetUtils.NumBitsInAByte - numBitstoShift); + inputLsb = (inputLsb < 0) ? (inputLsb + 256) : inputLsb; + inputMsb = inputBytes[i] & getMSBMask(numBitstoShift); + inputMsb = (inputBytes[i] < 0) ? (inputBytes[i] + 256) + : inputBytes[i]; + shiftedBytes[i] = (byte) ((inputLsb << numBitstoShift) | (inputMsb >> (NetUtils.NumBitsInAByte - numBitstoShift))); + } + inputMsb = inputBytes[0] & (getMSBMask(numBitstoShift)); + inputMsb = (inputMsb < 0) ? (inputMsb + 256) : inputMsb; + shiftedBytes[0] = (byte) (inputMsb >> (NetUtils.NumBitsInAByte - numBitstoShift)); + return shiftedBytes; + } + + /** + * Insert in the data buffer at position dictated by the offset the number + * of bits specified from the input data byte array. + * The input byte array has the bits stored starting from the LSB + * + * @param byte[] data + * @param byte[] inputdata + * @param int startOffset + * @param int numBits + * @return void + */ + public static void insertBits(byte[] data, byte[] inputdataLSB, + int startOffset, int numBits) { + byte[] inputdata = shiftBitsToMSB(inputdataLSB, numBits); // Align to MSB the passed byte array + int numBytes = numBits / NetUtils.NumBitsInAByte; + int startByteOffset = startOffset / NetUtils.NumBitsInAByte; + int extraOffsetBits = startOffset % NetUtils.NumBitsInAByte; + int extranumBits = numBits % NetUtils.NumBitsInAByte; + int RestBits = numBits % NetUtils.NumBitsInAByte; + int InputMSBbits = 0, InputLSBbits = 0; + int i; + + if (numBits == 0) + return; + + if (extraOffsetBits == 0) { + if (extranumBits == 0) { + numBytes = numBits / NetUtils.NumBitsInAByte; + System.arraycopy(inputdata, 0, data, startByteOffset, numBytes); + } else { + System.arraycopy(inputdata, 0, data, startByteOffset, numBytes); + data[startByteOffset + numBytes] = (byte) (data[startByteOffset + + numBytes] | (inputdata[numBytes] & getMSBMask(extranumBits))); + } + } else { + for (i = 0; i < numBytes; i++) { + if (i != 0) + InputLSBbits = (inputdata[i - 1] & getLSBMask(extraOffsetBits)); + InputMSBbits = (byte) (inputdata[i] & (getMSBMask(NetUtils.NumBitsInAByte + - extraOffsetBits))); + InputMSBbits = (InputMSBbits >= 0) ? InputMSBbits + : InputMSBbits + 256; + data[startByteOffset + i] = (byte) (data[startByteOffset + i] + | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)) | (InputMSBbits >> extraOffsetBits)); + InputMSBbits = InputLSBbits = 0; + } + if (RestBits < (NetUtils.NumBitsInAByte - extraOffsetBits)) { + if (numBytes != 0) + InputLSBbits = (inputdata[i - 1] & getLSBMask(extraOffsetBits)); + InputMSBbits = (byte) (inputdata[i] & (getMSBMask(RestBits))); + InputMSBbits = (InputMSBbits >= 0) ? InputMSBbits + : InputMSBbits + 256; + data[startByteOffset + i] = (byte) ((data[startByteOffset + i]) + | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)) | (InputMSBbits >> extraOffsetBits)); + } else if (RestBits == (NetUtils.NumBitsInAByte - extraOffsetBits)) { + if (numBytes != 0) + InputLSBbits = (inputdata[i - 1] & getLSBMask(extraOffsetBits)); + InputMSBbits = (byte) (inputdata[i] & (getMSBMask(NetUtils.NumBitsInAByte + - extraOffsetBits))); + InputMSBbits = (InputMSBbits >= 0) ? InputMSBbits + : InputMSBbits + 256; + data[startByteOffset + i] = (byte) (data[startByteOffset + i] + | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)) | (InputMSBbits >> extraOffsetBits)); + } else { + if (numBytes != 0) + InputLSBbits = (inputdata[i - 1] & getLSBMask(extraOffsetBits)); + InputMSBbits = (byte) (inputdata[i] & (getMSBMask(NetUtils.NumBitsInAByte + - extraOffsetBits))); + InputMSBbits = (InputMSBbits >= 0) ? InputMSBbits + : InputMSBbits + 256; + data[startByteOffset + i] = (byte) (data[startByteOffset + i] + | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)) | (InputMSBbits >> extraOffsetBits)); + + InputLSBbits = (inputdata[i] & (getLSBMask(RestBits + - (NetUtils.NumBitsInAByte - extraOffsetBits)) << (NetUtils.NumBitsInAByte - RestBits))); + data[startByteOffset + i + 1] = (byte) (data[startByteOffset + + i + 1] | (InputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))); + } + } + } + + /** + * Checks for overflow and underflow exceptions + * @param data + * @param startOffset + * @param numBits + * @throws Exception + */ + public static void checkExceptions(byte[] data, int startOffset, int numBits) + throws Exception { + int endOffsetByte; + int startByteOffset; + endOffsetByte = startOffset + / NetUtils.NumBitsInAByte + + numBits + / NetUtils.NumBitsInAByte + + ((numBits % NetUtils.NumBitsInAByte != 0) ? 1 : ((startOffset + % NetUtils.NumBitsInAByte != 0) ? 1 : 0)); + startByteOffset = startOffset / NetUtils.NumBitsInAByte; + + if (data == null) { + throw new Exception("data[] is null\n"); + } + + if ((startOffset < 0) || (startByteOffset >= data.length) + || (endOffsetByte > data.length) || (numBits < 0) + || (numBits > NetUtils.NumBitsInAByte * data.length)) { + throw new Exception( + "Illegal arguement/out of bound exception - data.length = " + + data.length + " startOffset = " + startOffset + + " numBits " + numBits); + } + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Ethernet.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Ethernet.java new file mode 100644 index 0000000000..0d866d644e --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Ethernet.java @@ -0,0 +1,143 @@ + +/* + * 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.controller.sal.packet; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.utils.EtherTypes; + +/** + * Class that represents the Ethernet frame objects + * + * + */ +public class Ethernet extends Packet { + private static final String DMAC = "DestinationMACAddress"; + private static final String SMAC = "SourceMACAddress"; + private static final String ETHT = "EtherType"; + + // TODO: This has to be outside and it should be possible for osgi + // to add new coming packet classes + public static Map> etherTypeClassMap; + static { + etherTypeClassMap = new HashMap>(); + etherTypeClassMap.put(EtherTypes.ARP.shortValue(), ARP.class); + etherTypeClassMap.put(EtherTypes.IPv4.shortValue(), IPv4.class); + etherTypeClassMap.put(EtherTypes.LLDP.shortValue(), LLDP.class); + } + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + { + put(DMAC, new ImmutablePair(0, 48)); + put(SMAC, new ImmutablePair(48, 48)); + put(ETHT, new ImmutablePair(96, 16)); + } + }; + private Map fieldValues; + + /** + * Default constructor that creates and sets the HashMap + */ + public Ethernet() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + /** + * Constructor that sets the access level for the packet and + * creates and sets the HashMap + */ + public Ethernet(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + @Override + public void setHeaderField(String headerField, byte[] readValue) { + if (headerField.equals(ETHT)) { + payloadClass = etherTypeClassMap.get(BitBufferHelper + .getShort(readValue)); + } + hdrFieldsMap.put(headerField, readValue); + } + + /** + * Gets the destination MAC address stored + * @return byte[] - the destinationMACAddress + */ + public byte[] getDestinationMACAddress() { + return fieldValues.get(DMAC); + } + + /** + * Gets the source MAC address stored + * @return byte[] - the sourceMACAddress + */ + public byte[] getSourceMACAddress() { + return fieldValues.get(SMAC); + } + + /** + * Gets the etherType stored + * @return short - the etherType + */ + public short getEtherType() { + return BitBufferHelper.getShort(fieldValues.get(ETHT)); + } + + /** + * Sets the destination MAC address for the current Ethernet object instance + * @param byte[] - the destinationMACAddress to set + */ + public Ethernet setDestinationMACAddress(byte[] destinationMACAddress) { + fieldValues.put(DMAC, destinationMACAddress); + return this; + } + + /** + * Sets the source MAC address for the current Ethernet object instance + * @param byte[] - the sourceMACAddress to set + */ + public Ethernet setSourceMACAddress(byte[] sourceMACAddress) { + fieldValues.put(SMAC, sourceMACAddress); + return this; + } + + /** + * Sets the etherType for the current Ethernet object instance + * @param short - the etherType to set + */ + public Ethernet setEtherType(short etherType) { + byte[] ethType = BitBufferHelper.toByteArray(etherType); + fieldValues.put(ETHT, ethType); + return this; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ICMP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ICMP.java new file mode 100644 index 0000000000..d1f81c5775 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ICMP.java @@ -0,0 +1,127 @@ + +/* + * 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.controller.sal.packet; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +/** + * Class that represents the ICMP packet objects + * + * + */ + +public class ICMP extends Packet { + private static final String TYPECODE = "TypeCode"; + private static final String CODE = "Code"; + private static final String HEADERCHECKSUM = "HeaderChecksum"; + private static final String IDENTIFIER = "Identifier"; + private static final String SEQNUMBER = "SequenceNumber"; + + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + + { + put(TYPECODE, new ImmutablePair(0, 8)); + put(CODE, new ImmutablePair(8, 8)); + put(HEADERCHECKSUM, new ImmutablePair(16, 16)); + put(IDENTIFIER, new ImmutablePair(32, 16)); + put(SEQNUMBER, new ImmutablePair(48, 16)); + + } + }; + + /** + * Default constructor that creates and sets the hash map values + */ + public ICMP() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + /** + * Constructor that sets the access level for the packet + */ + public ICMP(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + private Map fieldValues; + + @Override + public void setHeaderField(String headerField, byte[] readValue) { + hdrFieldsMap.put(headerField, readValue); + } + + /** + * Sets the TypeCode of ICMP for the current ICMP object instance + * @param short - typeCode + * @return ICMP + */ + public ICMP setTypeCode(short typeCode) { + byte[] icmpTypeCode = BitBufferHelper.toByteArray(typeCode); + fieldValues.put(TYPECODE, icmpTypeCode); + return this; + } + + /** + * Sets the ICMP checksum for the current ICMP object instance + * @param short - checksum + * @return ICMP + */ + public ICMP setChecksum(short checksum) { + byte[] icmpChecksum = BitBufferHelper.toByteArray(checksum); + fieldValues.put(HEADERCHECKSUM, icmpChecksum); + return this; + } + + /** + * Sets the ICMP identifier for the current ICMP object instance + * @param short - identifier + * @return ICMP + */ + public ICMP setIdentifier(short identifier) { + byte[] icmpIdentifier = BitBufferHelper.toByteArray(identifier); + fieldValues.put(IDENTIFIER, icmpIdentifier); + return this; + } + + /** + * Sets the ICMP sequence number for the current ICMP object instance + * @param short - seqNumber + * @return ICMP + */ + public ICMP setSequenceNumber(short seqNumber) { + byte[] icmpSeqNumber = BitBufferHelper.toByteArray(seqNumber); + fieldValues.put(SEQNUMBER, icmpSeqNumber); + return this; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IDataPacketService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IDataPacketService.java new file mode 100644 index 0000000000..c430518dd9 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IDataPacketService.java @@ -0,0 +1,49 @@ + +/* + * 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 + */ + +/** + * @file IDataPacketService.java + * + * @brief SAL exported Data Packet services + * + * Data Packet Services SAL provides to the components + */ +package org.opendaylight.controller.sal.packet; + +/** + * Data Packet Services SAL provides to the components + */ +public interface IDataPacketService { + /** + * Transmit a data Packet. Transmission will ONLY happen if the + * RawPacket has the OutgoingNodeConnector set else of course + * transmission cannot happen. + * + * @param outPkt Packet to be transmitted out + */ + void transmitDataPacket(RawPacket outPkt); + + /** + * Decode a Data Packet received as a raw stream + * + * @param pkt Raw Packet to be decoded + * + * @return The formatted Data Packet + */ + Packet decodeDataPacket(RawPacket pkt); + + /** + * Encode a Formatted Data Packet in a raw bytestream + * + * @param pkt Formatted Data Packet to be encoded + * + * @return a RawPacket representation, good for transmission purpose + */ + RawPacket encodeDataPacket(Packet pkt); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IListenDataPacket.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IListenDataPacket.java new file mode 100644 index 0000000000..76e2a6fbfe --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IListenDataPacket.java @@ -0,0 +1,70 @@ + +/* + * 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 + */ + +/** + * @file IListenDataPacket.java + * + * @brief Interface a component will need to implement and export as + * implemented interface in order to get data packet + * + * Interface a component will need to implement and export as + * implemented interface in order to get data packet + */ + +package org.opendaylight.controller.sal.packet; + +/** + * Interface that all the components that want to receive a dataPacket + * need to implement. The interface by itself doesn't specify any + * filtering or sequencing mechanism, but the model supported by Data + * Packet Service is such that the packets can be processed in two + * ways: + * - Serial: When a Data Packet Listener gets a packet after another, + * this case is necessary when the subsequent handler needs some extra + * information that can only be provided by another Data Packet + * Service Handler. If the dependent service is missing, then the one + * with dependencies will not be invoked. In a serial + * processing, a plugin has the the power to prevent the packet to be + * seen but other in the chain, if the return result is CONSUMED, else + * the packet will go through all the elements in the chain. + * - Parallel: When a Data Packet Listener doesn't express any + * dependency then it will get a copy of the packet as anybody + * else. Practical example, let say we have 2 handlers, both didn't + * express any dependency then both will get a copy of any incoming + * packet and they cannot step over each other feet. + * The Processing model is choosen by the properties with which the + * service is registered in the OSGi service registry. + * The properties that will be looked at are: + * salListenerName: Unique identifier of the SAL Data Packet + * Listener + * salListenerDependency: A String containing the + * salListenerName that consitute a dependency for this Listener, for + * now ONLY a SINGLE dependency is supported + * salListenerFilter: A Match class to be used to match a DataPacket, + * processing either parallel or serial will ONLY continue if the + * incoming DataPacket match the filter. If no filter is provided, the + * handler is called for EVERY packet i.e. match All is implied! + */ +public interface IListenDataPacket { + /** + * Handler for receiving the packet. The application can signal + * back to SAL if the packet has been consumed or no. In case of + * packet consumed SAL will prevent to keep passing to subsequent + * listener in the serial chain, but for handlers without + * dependency things will keep going . + * The packet will received will have the IncomingNodeConnector + * set to understand where the packet is coming from + * + * @param inPkt Packet received + * + * @return An indication if the packet should still be processed + * or we should stop it. + */ + PacketResult receiveDataPacket(RawPacket inPkt); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPluginInDataPacketService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPluginInDataPacketService.java new file mode 100644 index 0000000000..8252715ab7 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPluginInDataPacketService.java @@ -0,0 +1,35 @@ + +/* + * 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 + */ + +/** + * @file IPluginInDataPacketService.java + * + * @brief Data Packet Services exported by SouthBound plugins for SAL usage + * + * Data Packet Services exported by SouthBound plugins for SAL usage + */ +package org.opendaylight.controller.sal.packet; + +/** + * Data Packet Services exported by SouthBound plugins for SAL usage. + * The service will be used by SAL such that for every Protocol Plugin + * there is only one expected, for this reason the service need to be + * registered in the OSGi service registry along with the property: + * - "protocoloPluginType" + * the value of the property will org.opendaylight.controller.sal.core.Node.NodeIDType + */ +public interface IPluginInDataPacketService { + /** + * Transmit a data Packet. Packet will go out ONLY if the packet + * has property OutgoingNodeConnector set. + * + * @param outPkt Packet to be transmitted out + */ + void transmitDataPacket(RawPacket outPkt); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPluginOutDataPacketService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPluginOutDataPacketService.java new file mode 100644 index 0000000000..10667fdac8 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPluginOutDataPacketService.java @@ -0,0 +1,42 @@ + +/* + * 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 + */ + +/** + * @file IPluginOutDataPacketService.java + * + * @brief Interface SAL will need to register in order to get some + * packets from the southbound protocol plugins + * + * Interface SAL will need to register in order to get some + * packets from the southbound protocol plugins + */ + +package org.opendaylight.controller.sal.packet; + +/** + * Interface used by SAL to intercept any Data Packet coming from the + * southbound protocol plugins + */ +public interface IPluginOutDataPacketService { + /** + * Handler for receiving the packet. The SAL layer can signal back + * to the southbound plugin if the packet has been consumed or can + * go for further processing. Usually after SAL processing + * probably there is no other processing to be done, but just in + * case there is chain the return code can be used. + * The protocol plugin is supposed to deliver a packet with the + * IncomingNodeConnector set + * + * @param inPkt Packet received + * + * @return An indication if the packet should still be processed + * or we should stop it. + */ + PacketResult receiveDataPacket(RawPacket inPkt); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPv4.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPv4.java new file mode 100644 index 0000000000..b1fef8f1a5 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPv4.java @@ -0,0 +1,551 @@ + +/* + * 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.controller.sal.packet; + +import java.net.InetAddress; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Random; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.utils.IPProtocols; +import org.opendaylight.controller.sal.utils.NetUtils; + +/** + * Class that represents the IPv4 packet objects + * + * + */ + +public class IPv4 extends Packet { + private static final String VERSION = "Version"; + private static final String HEADERLENGTH = "HeaderLength"; + private static final String DIFFSERV = "DiffServ"; + private static final String ECN = "ECN"; + private static final String TOTLENGTH = "TotalLength"; + private static final String IDENTIFICATION = "Identification"; + private static final String FLAGS = "Flags"; + private static final String FRAGOFFSET = "FragmentOffset"; + private static final String TTL = "TTL"; + private static final String PROTOCOL = "Protocol"; + private static final String CHECKSUM = "Checksum"; + private static final String SIP = "SourceIPAddress"; + private static final String DIP = "DestinationIPAddress"; + private static final String OPTIONS = "Options"; + + public static Map> protocolClassMap; + static { + protocolClassMap = new HashMap>(); + protocolClassMap.put(IPProtocols.ICMP.byteValue(), ICMP.class); + protocolClassMap.put(IPProtocols.UDP.byteValue(), UDP.class); + protocolClassMap.put(IPProtocols.TCP.byteValue(), TCP.class); + } + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + { + put(VERSION, new ImmutablePair(0, 4)); + put(HEADERLENGTH, new ImmutablePair(4, 4)); + put(DIFFSERV, new ImmutablePair(8, 6)); + put(ECN, new ImmutablePair(14, 2)); + put(TOTLENGTH, new ImmutablePair(16, 16)); + put(IDENTIFICATION, new ImmutablePair(32, 16)); + put(FLAGS, new ImmutablePair(48, 3)); + put(FRAGOFFSET, new ImmutablePair(51, 13)); + put(TTL, new ImmutablePair(64, 8)); + put(PROTOCOL, new ImmutablePair(72, 8)); + put(CHECKSUM, new ImmutablePair(80, 16)); + put(SIP, new ImmutablePair(96, 32)); + put(DIP, new ImmutablePair(128, 32)); + put(OPTIONS, new ImmutablePair(160, 0)); + } + }; + + private Map fieldValues; + + /** + * Default constructor that sets the version to 4, headerLength to 5, + * and flags to 2. The default value for the identification is set to a + * random number and the remaining fields are set to 0. + */ + public IPv4() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + + setVersion((byte) 4); + setHeaderLength((byte) 5); + setDiffServ((byte) 0); + setIdentification(generateId()); + setFlags((byte) 2); + setFragmentOffset((short) 0); + setECN((byte) 0); + } + + /** + * The write access to the packet is set in this constructor. + * Constructor that sets the version to 4, headerLength to 5, + * and flags to 2. The default value for the identification is set to a + * random number and the remaining fields are set to 0. + * @param boolean + */ + public IPv4(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + + setVersion((byte) 4); + setHeaderLength((byte) 5); + setDiffServ((byte) 0); + setIdentification(generateId()); + setFlags((byte) 2); + setFragmentOffset((short) 0); + setECN((byte) 0); + } + + /** + * Gets the IP version stored + * @return the version + */ + public byte getVersion() { + return (BitBufferHelper.getByte(fieldValues.get(VERSION))); + } + + /** + * Gets the IP header length stored + * @return the headerLength in bytes + */ + public int getHeaderLen() { + return (4 * BitBufferHelper.getByte(fieldValues.get(HEADERLENGTH))); + } + + /** + * Gets the header length in bits, from the header length stored and options if any + * @return HeaderLength to serialize code + */ + @Override + public int getHeaderSize() { + int headerLen = this.getHeaderLen(); + if (headerLen == 0) + headerLen = 20; + + byte[] options = hdrFieldsMap.get(OPTIONS); + if (options != null) + headerLen += options.length; + + return headerLen * NetUtils.NumBitsInAByte; + + } + + /** + * Gets the differential services value stored + * @return the diffServ + */ + public byte getDiffServ() { + return BitBufferHelper.getByte(fieldValues.get(DIFFSERV)); + } + + /** + * Gets the ecn bits stored + * @return the ecn bits + */ + public byte getECN() { + return BitBufferHelper.getByte(fieldValues.get(ECN)); + } + + /** + * Gets the total length of the IP header in bytes + * @return the totalLength + */ + public short getTotalLength() { + return (BitBufferHelper.getShort(fieldValues.get(TOTLENGTH))); + } + + /** + * Gets the identification value stored + * @return the identification + */ + public short getIdentification() { + return (BitBufferHelper.getShort(fieldValues.get(IDENTIFICATION))); + } + + /** + * Gets the flag values stored + * @return the flags + */ + public byte getFlags() { + return (BitBufferHelper.getByte(fieldValues.get(FLAGS))); + } + + /** + * Gets the TTL value stored + * @return the ttl + */ + public byte getTtl() { + return (BitBufferHelper.getByte(fieldValues.get(TTL))); + } + + /** + * Gets the protocol value stored + * @return the protocol + */ + public byte getProtocol() { + return (BitBufferHelper.getByte(fieldValues.get(PROTOCOL))); + } + + /** + * Gets the checksum value stored + * @return the checksum + */ + public short getChecksum() { + return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM))); + } + + /** + * Gets the fragment offset stored + * @return the fragmentOffset + */ + public short getFragmentOffset() { + return (BitBufferHelper.getShort(fieldValues.get(FRAGOFFSET))); + } + + /** + * Gets the source IP address stored + * @return the sourceAddress + */ + public int getSourceAddress() { + return (BitBufferHelper.getInt(fieldValues.get(SIP))); + } + + /** + * Gets the destination IP address stored + * @return the destinationAddress + */ + public int getDestinationAddress() { + return (BitBufferHelper.getInt(fieldValues.get(DIP))); + } + + /** + * gets the Options stored + * @return the options + */ + public byte[] getOptions() { + return (fieldValues.get(OPTIONS)); + } + + @Override + /** + * Stores the value of fields read from data stream + * Variable header value like payload protocol, is stored here + */ + public void setHeaderField(String headerField, byte[] readValue) { + if (headerField.equals(PROTOCOL)) { + payloadClass = protocolClassMap.get(readValue[0]); + } + hdrFieldsMap.put(headerField, readValue); + } + + /** + * Stores the IP version from the header + * @param version the version to set + * @return @IPv4 + */ + public IPv4 setVersion(byte ipVersion) { + byte[] version = BitBufferHelper.toByteArray(ipVersion); + fieldValues.put(VERSION, version); + return this; + } + + /** + * Stores the length of IP header in words (2 bytes) + * @param headerLength the headerLength to set + * @return IPv4 + */ + public IPv4 setHeaderLength(byte ipheaderLength) { + byte[] headerLength = BitBufferHelper.toByteArray(ipheaderLength); + fieldValues.put(HEADERLENGTH, headerLength); + return this; + } + + /** + * Stores the differential services value from the IP header + * @param diffServ the diffServ to set + * @return IPv4 + */ + public IPv4 setDiffServ(byte ipdiffServ) { + byte[] diffServ = BitBufferHelper.toByteArray(ipdiffServ); + fieldValues.put(DIFFSERV, diffServ); + return this; + } + + /** + * Stores the ECN bits from the header + * @param ECN bits to set + * @return IPv4 + */ + public IPv4 setECN(byte ecn) { + byte[] ecnbytes = BitBufferHelper.toByteArray(ecn); + fieldValues.put(ECN, ecnbytes); + return this; + } + + /** + * Stores the total length of IP header in bytes + * @param totalLength the totalLength to set + * @return IPv4 + */ + public IPv4 setTotalLength(short iptotalLength) { + byte[] totalLength = BitBufferHelper.toByteArray(iptotalLength); + fieldValues.put(TOTLENGTH, totalLength); + return this; + } + + /** + * Stores the identification number from the header + * @param identification the identification to set + * @return IPv4 + */ + public IPv4 setIdentification(short ipIdentification) { + byte[] identification = BitBufferHelper.toByteArray(ipIdentification); + fieldValues.put(IDENTIFICATION, identification); + return this; + } + + /** + * Stores the IP flags value + * @param flags the flags to set + * @return IPv4 + */ + public IPv4 setFlags(byte ipFlags) { + byte[] flags = { ipFlags }; + fieldValues.put(FLAGS, flags); + return this; + } + + /** + * Stores the IP fragmentation offset value + * @param fragmentOffset the fragmentOffset to set + * @return IPv4 + */ + public IPv4 setFragmentOffset(short ipFragmentOffset) { + byte[] fragmentOffset = BitBufferHelper.toByteArray(ipFragmentOffset); + fieldValues.put(FRAGOFFSET, fragmentOffset); + return this; + } + + /** + * Stores the TTL value + * @param ttl the ttl to set + * @return IPv4 + */ + public IPv4 setTtl(byte ipTtl) { + byte[] ttl = BitBufferHelper.toByteArray(ipTtl); + fieldValues.put(TTL, ttl); + return this; + } + + /** + * Stores the protocol value of the IP payload + * @param protocol the protocol to set + * @return IPv4 + */ + public IPv4 setProtocol(byte ipProtocol) { + byte[] protocol = BitBufferHelper.toByteArray(ipProtocol); + fieldValues.put(PROTOCOL, protocol); + return this; + } + + /** + * @param checksum the checksum to set + */ + /*public IPv4 setChecksum() { + short ipChecksum = computeChecksum(); + byte[] checksum = BitBufferHelper.toByteArray(ipChecksum); + fieldValues.put(CHECKSUM, checksum); + return this; + }*/ + + /** + * Stores the IP source address from the header + * @param sourceAddress the sourceAddress to set + * @return IPv4 + */ + public IPv4 setSourceAddress(InetAddress ipSourceAddress) { + byte[] sourceAddress = ipSourceAddress.getAddress(); + fieldValues.put(SIP, sourceAddress); + return this; + } + + /** + * Stores the IP destination address from the header + * @param the destination Address to set + * @return IPv4 + */ + public IPv4 setDestinationAddress(InetAddress ipDestinationAddress) { + byte[] sourceAddress = ipDestinationAddress.getAddress(); + fieldValues.put(DIP, sourceAddress); + return this; + } + + /** + * Stores the IP destination address from the header + * @param destinationAddress the destinationAddress to set + * @return IPv4 + */ + public IPv4 setDestinationAddress(int ipDestinationAddress) { + byte[] destinationAddress = BitBufferHelper + .toByteArray(ipDestinationAddress); + fieldValues.put(DIP, destinationAddress); + return this; + } + + /** + * Generate a random number to set the Identification field + * in IPv4 Header + * @return short + */ + private short generateId() { + Random randomgen = new Random(); + return (short) (randomgen.nextInt(Short.MAX_VALUE + 1)); + } + + /** + * Store the options from IP header + * @param options - byte[] + * @return IPv4 + */ + public IPv4 setOptions(byte[] options) { + fieldValues.put(OPTIONS, options); + byte newIHL = (byte) (5 + options.length); + setHeaderLength(newIHL); + + return this; + } + + /** + * Computes the header checksum + * @param byte[] hdrBytes - serialized bytes + * @param int endBitOffset - end bit Offset + * @return short - the computed checksum + */ + private short computeChecksum(byte[] hdrBytes, int endByteOffset) { + int startByteOffset = endByteOffset - getHeaderLen(); + short checkSum = (short) 0; + int sum = 0, carry = 0, finalSum = 0; + int parsedHex = 0; + int checksumStartByte = startByteOffset + getfieldOffset(CHECKSUM) + / NetUtils.NumBitsInAByte; + + for (int i = startByteOffset; i <= (endByteOffset - 1); i = i + 2) { + //Skip, if the current bytes are checkSum bytes + if (i == checksumStartByte) + continue; + StringBuffer sbuffer = new StringBuffer(); + sbuffer.append(String.format("%02X", hdrBytes[i])); + if (i < (hdrBytes.length - 1)) + sbuffer.append(String.format("%02X", hdrBytes[i + 1])); + + parsedHex = Integer.valueOf(sbuffer.toString(), 16); + sum += parsedHex; + } + carry = (sum >> 16) & 0xFF; + finalSum = (sum & 0xFFFF) + carry; + checkSum = (short) ~((short) finalSum & 0xFFFF); + return checkSum; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + /** + * Gets the number of bits for the fieldname specified + * If the fieldname has variable length like "Options", then this value is computed using the + * options length and the header length + * @param fieldname - String + * @return number of bits for fieldname - int + */ + public int getfieldnumBits(String fieldName) { + if (fieldName.equals(OPTIONS)) { + byte[] options = getOptions(); + return ((options == null) ? 0 : (options.length - getHeaderLen())); + } + return (((Pair) hdrFieldCoordMap.get(fieldName)) + .getRight()); + } + + @Override + /** + * Method to perform post serialization - like computation of checksum of serialized header + * @param serializedBytes + * @return void + * @Exception throws exception + */ + protected void postSerializeCustomOperation(byte[] serializedBytes) + throws Exception { + int startOffset = this.getfieldOffset(CHECKSUM); + int numBits = this.getfieldnumBits(CHECKSUM); + byte[] checkSum = BitBufferHelper.toByteArray(computeChecksum( + serializedBytes, serializedBytes.length)); + BitBufferHelper.setBytes(serializedBytes, checkSum, startOffset, + numBits); + return; + } + + @Override + /** + * Stores the payload of IP, serializes it and stores the length of serialized payload + * bytes in Total Length + * @param payload - Packet + */ + public void setPayload(Packet payload) { + this.payload = payload; + /* + * Deriving the Total Lenght here + * TODO: See if we can derive the total length during + * another phase (during serialization/deserialization) + * */ + int payloadLength = 0; + try { + payloadLength = payload.serialize().length; + } catch (Exception e) { + e.printStackTrace(); + } + this.setTotalLength((short) (this.getHeaderLen() + payloadLength)); + } + + @Override + /** + * Method to perform post deserialization - like compare computed checksum with + * the one obtained from IP header + */ + protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) { + int endByteOffset = endBitOffset / NetUtils.NumBitsInAByte; + int computedChecksum = computeChecksum(data, endByteOffset); + int actualChecksum = BitBufferHelper.getInt(fieldValues.get(CHECKSUM)); + if (computedChecksum != actualChecksum) + corrupted = true; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDP.java new file mode 100644 index 0000000000..420614ffbd --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDP.java @@ -0,0 +1,211 @@ + +/* + * 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.controller.sal.packet; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.opendaylight.controller.sal.utils.NetUtils; + +/** + * Class that represents the LLDP frame objects + */ + +public class LLDP extends Packet { + private static final String CHASSISID = "ChassisId"; + private static final String PORTID = "PortId"; + private static final String TTL = "TTL"; + private static final int LLDPDefaultTlvs = 3; + private static LLDPTLV emptyTLV = new LLDPTLV().setLength((short)0).setType((byte)0); + public static final byte[] LLDPMulticastMac = {1,(byte)0x80,(byte)0xc2, 0, 0,(byte)0xe}; + private Map tlvList; + + /** + * Default constructor that creates the tlvList LinkedHashMap + */ + public LLDP() { + super(); + tlvList = new LinkedHashMap(LLDPDefaultTlvs); + } + + /** + * Constructor that creates the tlvList LinkedHashMap and sets + * the write access for the same + */ + public LLDP (boolean writeAccess) { + super(writeAccess); + tlvList = new LinkedHashMap(LLDPDefaultTlvs); // Mandatory TLVs + } + + /** + * @param String - description of the type of TLV + * @return byte - type of TLV + */ + private byte getType(String typeDesc) { + if (typeDesc.equals(CHASSISID)) { + return LLDPTLV.TLVType.ChassisID.getValue(); + } else if (typeDesc.equals(PORTID)) { + return LLDPTLV.TLVType.PortID.getValue(); + } else if (typeDesc.equals(TTL)) { + return LLDPTLV.TLVType.TTL.getValue(); + } else { + return LLDPTLV.TLVType.Unknown.getValue(); + } + } + + /** + * @param String - description of the type of TLV + * @return LLDPTLV - full TLV + */ + public LLDPTLV getTLV(String type) { + return tlvList.get(getType(type)); + } + + /** + * @param String - description of the type of TLV + * @param LLDPTLV - tlv to set + * @return void + */ + public void setTLV(String type, LLDPTLV tlv) { + tlvList.put(getType(type), tlv); + } + + /** + * @return the chassisId TLV + */ + public LLDPTLV getChassisId() { + return getTLV(CHASSISID); + } + + /** + * @param LLDPTLV - the chassisId to set + */ + public LLDP setChassisId(LLDPTLV chassisId) { + tlvList.put(getType(CHASSISID), chassisId); + return this; + } + + /** + * @return LLDPTLV - the portId TLV + */ + public LLDPTLV getPortId() { + return tlvList.get(getType(PORTID)); + } + + /** + * @param LLDPTLV - the portId to set + * @return LLDP + */ + public LLDP setPortId(LLDPTLV portId) { + tlvList.put(getType(PORTID), portId); + return this; + } + + /** + * @return LLDPTLV - the ttl TLV + */ + public LLDPTLV getTtl() { + return tlvList.get(getType(TTL)); + } + + /** + * @param LLDPTLV - the ttl to set + * @return LLDP + */ + public LLDP setTtl(LLDPTLV ttl) { + tlvList.put(getType(TTL), ttl); + return this; + } + + /** + * @return the optionalTLVList + */ + public List getOptionalTLVList() { + List list = new ArrayList(); + for (Map.Entry entry : tlvList.entrySet()) { + byte type = entry.getKey(); + if ((type == LLDPTLV.TLVType.ChassisID.getValue()) || + (type == LLDPTLV.TLVType.PortID.getValue()) || + (type == LLDPTLV.TLVType.TTL.getValue())) { + continue; + } else { + list.add(entry.getValue()); + } + } + return list; + } + + /** + * @param optionalTLVList the optionalTLVList to set + * @return LLDP + */ + public LLDP setOptionalTLVList(List optionalTLVList) + { + for (LLDPTLV tlv : optionalTLVList) { + tlvList.put(tlv.getType(), tlv); + } + return this; + } + + @Override + public Packet deserialize (byte[] data, int bitOffset, int size) throws Exception { + int lldpOffset = bitOffset; // LLDP start + int lldpSize = size; // LLDP size + + /* + * Deserialize the TLVs until we reach the end of the packet + */ + + while (lldpSize > 0) { + LLDPTLV tlv = new LLDPTLV(); + tlv.deserialize(data, lldpOffset, lldpSize); + lldpOffset += tlv.getTLVSize(); //Size of current TLV in bits + lldpSize -= tlv.getTLVSize(); + this.tlvList.put(tlv.getType(), tlv); + } + return this; + } + + @Override + public byte[] serialize() throws Exception { + int startOffset = 0; + byte[] serializedBytes = new byte[getLLDPPacketLength()]; + + for (Map.Entry entry : tlvList.entrySet()) { + LLDPTLV tlv = entry.getValue(); + int numBits = tlv.getTLVSize(); + BitBufferHelper.setBytes(serializedBytes, tlv.serialize(), startOffset, numBits); + startOffset += numBits; + } + // Now add the empty LLDPTLV at the end + BitBufferHelper.setBytes(serializedBytes, LLDP.emptyTLV.serialize(), startOffset, LLDP.emptyTLV.getTLVSize()); + + return serializedBytes; + } + + /** + * Returns the size of LLDP packet in bytes + * @return int - LLDP Packet size in bytes + * @throws Exception + */ + private int getLLDPPacketLength() throws Exception { + int len = 0; + LLDPTLV tlv; + + for (Map.Entry entry : this.tlvList.entrySet()) { + tlv = entry.getValue(); + len += tlv.getTLVSize(); + } + len += LLDP.emptyTLV.getTLVSize(); + + return len/NetUtils.NumBitsInAByte; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java new file mode 100644 index 0000000000..a89816ffaf --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java @@ -0,0 +1,279 @@ + +/* + * 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.controller.sal.packet; + +import java.io.UnsupportedEncodingException; +import java.util.HashMap; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.utils.HexEncode; +import org.opendaylight.controller.sal.utils.NetUtils; + +/** + * Class that represents the LLDPTLV objects + */ + +public class LLDPTLV extends Packet { + private static final String TYPE = "Type"; + private static final String LENGTH = "Length"; + private static final String VALUE = "Value"; + private static final int LLDPTLVFields = 3; + public static final byte[] OFOUI = new byte[] {(byte)0x00, (byte)0x26, (byte)0xe1}; // OpenFlow OUI + public static final byte[] customTlvSubType = new byte[] {0}; + public static final int customTlvOffset = OFOUI.length + customTlvSubType.length; + public static final byte chassisIDSubType[] = new byte[] {4}; // MAC address for the system + public static final byte portIDSubType[] = new byte[] {7}; // locally assigned + + public enum TLVType { + Unknown ((byte)0), + ChassisID ((byte)1), + PortID ((byte)2), + TTL ((byte)3), + PortDesc ((byte)4), + SystemName ((byte)5), + SystemDesc ((byte)6), + Custom ((byte)127); + + private byte value; + private TLVType(byte value) { + this.value = value; + } + public byte getValue() { + return value; + } + } + + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + + { + put(TYPE, new MutablePair(0, 7)); + put(LENGTH, new MutablePair(7, 9)); + put(VALUE, new MutablePair(16, 0)); + } + }; + + protected Map fieldValues; + + /** + * Default constructor that creates and sets the hash map values + * and sets the payload to null + */ + public LLDPTLV() { + payload = null; + fieldValues = new HashMap(LLDPTLVFields); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + } + + /** + * Constructor that writes the passed LLDPTLV values to the + * hdrFieldsMap + */ + public LLDPTLV(LLDPTLV other) { + for (Map.Entry entry : other.hdrFieldsMap.entrySet()) { + this.hdrFieldsMap.put(entry.getKey(), entry.getValue()); + } + } + + /** + * @return int - the length of TLV + */ + public int getLength() { + return (int) BitBufferHelper.toNumber(fieldValues.get(LENGTH), + fieldCoordinates.get(LENGTH).getRight().intValue()); + } + + /** + * @return byte - the type of TLV + */ + public byte getType() { + return BitBufferHelper.getByte(fieldValues.get(TYPE)); + } + + /** + * @return byte[] - the value field of TLV + */ + public byte[] getValue() { + return fieldValues.get(VALUE); + } + + /** + * @param byte - the type to set + * @return LLDPTLV + */ + public LLDPTLV setType(byte type) { + byte[] lldpTLVtype = { type }; + fieldValues.put(TYPE, lldpTLVtype); + return this; + } + + /** + * @param short - the length to set + * @return LLDPTLV + */ + public LLDPTLV setLength(short length) { + fieldValues.put(LENGTH, BitBufferHelper.toByteArray(length)); + return this; + } + + /** + * @param byte[] - the value to set + * @return LLDPTLV + */ + public LLDPTLV setValue(byte[] value) { + fieldValues.put(VALUE, value); + return this; + } + + @Override + public void setHeaderField(String headerField, byte[] readValue) { + hdrFieldsMap.put(headerField, readValue); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public int getfieldnumBits(String fieldName) throws Exception { + if (fieldName.equals(VALUE)) { + return (NetUtils.NumBitsInAByte * (int) BitBufferHelper.getShort( + fieldValues.get(LENGTH), fieldCoordinates.get(LENGTH) + .getRight().intValue())); + } + return fieldCoordinates.get(fieldName).getRight(); + } + + /** + * Returns the size in bits of the whole TLV + * @return int - size in bits of full TLV + * @throws Exception + */ + public int getTLVSize() throws Exception { + return (LLDPTLV.fieldCoordinates.get(TYPE).getRight() + // static + LLDPTLV.fieldCoordinates.get(LENGTH).getRight() + // static + getfieldnumBits(VALUE)); // variable + } + + /** + * Creates the ChassisID TLV value including the subtype and ChassisID string + * + * @param nodeId node identifier string + * @return the ChassisID TLV value in byte array + */ + static public byte[] createChassisIDTLVValue(String nodeId) { + byte[] cid = HexEncode.bytesFromHexString(nodeId); + byte[] cidValue = new byte[cid.length + chassisIDSubType.length]; + + System.arraycopy(chassisIDSubType, 0, cidValue, 0, chassisIDSubType.length); + System.arraycopy(cid, 0, cidValue, chassisIDSubType.length, cid.length); + + return cidValue; + } + + /** + * Creates the PortID TLV value including the subtype and PortID string + * + * @param portId port identifier string + * @return the PortID TLV value in byte array + */ + static public byte[] createPortIDTLVValue(String portId) { + byte[] pid = portId.getBytes(); + byte[] pidValue = new byte[pid.length + portIDSubType.length]; + + System.arraycopy(portIDSubType, 0, pidValue, 0, portIDSubType.length); + System.arraycopy(pid, 0, pidValue, portIDSubType.length, pid.length); + + return pidValue; + } + + /** + * Creates the custom TLV value including OUI, subtype and custom string + * + * @param portId port identifier string + * @return the custom TLV value in byte array + */ + static public byte[] createCustomTLVValue(String customString) { + byte[] customArray = customString.getBytes(); + byte[] customValue = new byte[customTlvOffset + customArray.length]; + + System.arraycopy(OFOUI, 0, customValue, 0, OFOUI.length); + System.arraycopy(customTlvSubType, 0, customValue, OFOUI.length, + customTlvSubType.length); + System.arraycopy(customArray, 0, customValue, customTlvOffset, + customArray.length); + + return customValue; + } + + /** + * Retrieves the string from TLV value and returns it in HexString format + * + * @param tlvValue the TLV value + * @param tlvLen the TLV length + * @return the HexString + */ + static public String getHexStringValue(byte[] tlvValue, int tlvLen) { + byte[] cidBytes = new byte[tlvLen - chassisIDSubType.length]; + System.arraycopy(tlvValue, chassisIDSubType.length, cidBytes, 0, cidBytes.length); + return HexEncode.bytesToHexStringWithColumn(cidBytes); + } + + /** + * Retrieves the string from TLV value + * + * @param tlvValue the TLV value + * @param tlvLen the TLV length + * @return the string + */ + static public String getStringValue(byte[] tlvValue, int tlvLen) { + byte[] pidBytes = new byte[tlvLen - portIDSubType.length]; + System.arraycopy(tlvValue, portIDSubType.length, pidBytes, 0, pidBytes.length); + return (new String(pidBytes)); + } + + /** + * Retrieves the custom string from the Custom TLV value which includes OUI, subtype and custom string + * + * @param customTlvValue the custom TLV value + * @param customTlvLen the custom TLV length + * @return the custom string + */ + static public String getCustomString(byte[] customTlvValue, int customTlvLen) { + String customString = ""; + byte[] vendor = new byte[3]; + System.arraycopy(customTlvValue, 0, vendor, 0, vendor.length); + if (Arrays.equals(vendor, LLDPTLV.OFOUI)) { + int customArrayLength = customTlvLen - customTlvOffset; + byte[] customArray = new byte[customArrayLength]; + System.arraycopy(customTlvValue, customTlvOffset, + customArray, 0, customArrayLength); + try { + customString = new String(customArray, "UTF-8"); + } catch (UnsupportedEncodingException e) { + } + } + + return customString; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LinkEncap.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LinkEncap.java new file mode 100644 index 0000000000..6d295dddb9 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LinkEncap.java @@ -0,0 +1,24 @@ + +/* + * 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 + */ + +/** + * @file LinkEncap.java + * + * @brief Enum some datalink packet format understood + * + * Enum some datalink packet format understood + */ +package org.opendaylight.controller.sal.packet; + +/** + * Describe a packet data link format + */ +public enum LinkEncap { + ETHERNET +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Packet.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Packet.java new file mode 100644 index 0000000000..61d6d248c8 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Packet.java @@ -0,0 +1,281 @@ + +/* + * 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.controller.sal.packet; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.utils.HexEncode; +import org.opendaylight.controller.sal.utils.NetUtils; + +/** + * Abstract class which represents the generic network packet object + * It provides the basic methods which are common for all the packets, + * like serialize and deserialize + * + * + */ + +public abstract class Packet { + // Access level granted to this packet + protected boolean writeAccess; + // When deserialized from wire, packet could result corrupted + protected boolean corrupted; + // The packet that encapsulate this packet + protected Packet parent; + // The packet encapsulated by this packet + protected Packet payload; + // Bit coordinates of packet header fields + protected Map> hdrFieldCoordMap; + // Header fields values: Map + protected Map hdrFieldsMap; + // The class of the encapsulated packet object + protected Class payloadClass; + + public Packet() { + writeAccess = false; + corrupted = false; + } + + public Packet(boolean writeAccess) { + this.writeAccess = writeAccess; + this.corrupted = false; + } + + public Packet getParent() { + return parent; + } + + public Packet getPayload() { + return payload; + } + + public void setParent(Packet parent) { + this.parent = parent; + } + + public void setPayload(Packet payload) { + this.payload = payload; + } + + public void setHeaderField(String headerField, byte[] readValue) { + hdrFieldsMap.put(headerField, readValue); + } + + /** + * This method deserializes the data bits obtained from the wire + * into the respective header and payload which are of type Packet + * @param byte[] data - data from wire to deserialize + * @param int bitOffset bit position where packet header starts in data array + * @param int size of packet in bits + * @return Packet + * @throws Exception + */ + + public Packet deserialize(byte[] data, int bitOffset, int size) + throws Exception { + String hdrField; + Integer startOffset = 0, numBits = 0; + byte[] hdrFieldBytes; + + for (Entry> pairs : hdrFieldCoordMap + .entrySet()) { + hdrField = pairs.getKey(); + startOffset = bitOffset + this.getfieldOffset(hdrField); + numBits = this.getfieldnumBits(hdrField); + + hdrFieldBytes = BitBufferHelper.getBits(data, startOffset, numBits); + /* + * Store the raw read value, checks the payload type and + * set the payloadClass accordingly + */ + this.setHeaderField(hdrField, hdrFieldBytes); + } + + postDeserializeCustomOperation(data, startOffset); + + int payloadStart = startOffset + numBits; + //int payloadSize = size - payloadStart; + int payloadSize = data.length * NetUtils.NumBitsInAByte - payloadStart; + + if (payloadClass != null) { + try { + payload = payloadClass.newInstance(); + } catch (Exception e) { + throw new RuntimeException( + "Error parsing payload for Ethernet packet", e); + } + payload.deserialize(data, payloadStart, payloadSize); + payload.setParent(this); + } else { + // For now let's discard unparsable payload + } + return this; + } + + /** + * This method serializes the header and payload bytes from + * the respective packet class, into a single stream of bytes + * to be sent on the wire + * @return byte[] - serialized bytes + * @throws Exception + */ + + public byte[] serialize() throws Exception { + byte[] payloadBytes = null; + int payloadSize = 0; + int headerSize = this.getHeaderSize(); + int payloadByteOffset = headerSize / NetUtils.NumBitsInAByte; + int size = 0; + + if (payload != null) { + payloadBytes = payload.serialize(); + payloadSize = payloadBytes.length * NetUtils.NumBitsInAByte; + } + + size = headerSize + payloadSize; + int length = size / NetUtils.NumBitsInAByte; + byte headerBytes[] = new byte[length]; + + if (payload != null) { + System.arraycopy(payloadBytes, 0, headerBytes, payloadByteOffset, + payloadBytes.length); + } + + String field; + byte[] fieldBytes; + Integer startOffset, numBits; + + for (Map.Entry> pairs : hdrFieldCoordMap + .entrySet()) { + field = pairs.getKey(); + fieldBytes = hdrFieldsMap.get(field); + // Let's skip optional fields when not set + if (fieldBytes != null) { + startOffset = this.getfieldOffset(field); + numBits = this.getfieldnumBits(field); + BitBufferHelper.setBytes(headerBytes, fieldBytes, startOffset, + numBits); + } + } + postSerializeCustomOperation(headerBytes); + + return headerBytes; + } + + /** + * This method gets called at the end of the serialization process + * It is intended for the child packets to insert some custom data + * into the output byte stream which cannot be done or cannot be done + * efficiently during the normal Packet.serialize() path. + * An example is the checksum computation for IPv4 + * @param byte[] - serialized bytes + */ + protected void postSerializeCustomOperation(byte[] myBytes) + throws Exception { + // no op + } + + /** + * This method re-computes the checksum of the bits received on the + * wire and validates it with the checksum in the bits received + * Since the computation of checksum varies based on the protocol, + * this method is overridden + * Currently only IPv4 does checksum computation and validation + * TCP and UDP need to implement these if required + * @param byte[] data + * @param int endBitOffset + * @return void + */ + protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) + throws Exception { + // no op + } + + /** + * Gets the header length in bits + * @return int + * @throws Exception + */ + public int getHeaderSize() throws Exception { + int size = 0; + /* + * We need to iterate over the fields that were read in the frame (hdrFieldsMap) + * not all the possible ones described in hdrFieldCoordMap. + * For ex, 802.1Q may or may not be there + */ + for (Map.Entry fieldEntry : hdrFieldsMap.entrySet()) { + if (fieldEntry.getValue() != null) { + String field = fieldEntry.getKey(); + size += getfieldnumBits(field); + } + } + return size; + } + + /** + * This method fetches the start bit offset for header field specified by + * 'fieldname'. The offset is present in the hdrFieldCoordMap of the respective + * packet class + * @param String fieldName + * @return Integer - startOffset of the requested field + */ + public int getfieldOffset(String fieldName) { + return (((Pair) hdrFieldCoordMap.get(fieldName)) + .getLeft()); + } + + /** + * This method fetches the number of bits for header field specified by + * 'fieldname'. The numBits are present in the hdrFieldCoordMap of the respective + * packet class + * @param String fieldName + * @return Integer - number of bits of the requested field + */ + public int getfieldnumBits(String fieldName) throws Exception { + return (((Pair) hdrFieldCoordMap.get(fieldName)) + .getRight()); + } + + @Override + public String toString() { + StringBuffer ret = new StringBuffer(); + for (Map.Entry entry : hdrFieldsMap.entrySet()) { + ret.append(entry.getKey() + ": "); + if (entry.getValue().length == 6) { + ret.append(HexEncode.bytesToHexString(entry.getValue()) + " "); + } else if (entry.getValue().length == 4) { + try { + ret.append(InetAddress.getByAddress(entry.getValue()) + .getHostAddress() + + " "); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + } else { + ret.append(((Long) BitBufferHelper.getLong(entry.getValue())) + .toString() + + " "); + } + } + return ret.toString(); + } + + /** + * Returns true if the packet is corrupted + * @return boolean + */ + protected boolean isPacketCorrupted() { + return corrupted; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/PacketResult.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/PacketResult.java new file mode 100644 index 0000000000..c2926579eb --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/PacketResult.java @@ -0,0 +1,40 @@ + +/* + * 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 + */ + +/** + * @file PacketResult.java + * + * @brief Possible results for Data packet processing handler + */ +package org.opendaylight.controller.sal.packet; + +/** + * Possible results for Data packet processing handler + * + */ +public enum PacketResult { + /** + * Packet has been processed and noone in the chain after us is + * supposed to see it + * + */ + CONSUME, + /** + * Packet has been processed and still further processing is + * possible + * + */ + KEEP_PROCESSING, + /** + * Packet has been ignored so further handler is present in + * the sequence need to still look at it. + * + */ + IGNORED +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/RawPacket.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/RawPacket.java new file mode 100644 index 0000000000..00befde7f1 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/RawPacket.java @@ -0,0 +1,196 @@ + +/* + * 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 + */ + +/** + * @file RawPacket.java + * + * @brief Describe a raw Data Packet, this is how a packet is + * received from the network and how it will be transmitted. It + * essentially wraps the raw bytestream + * + */ +package org.opendaylight.controller.sal.packet; + +import java.util.Map; +import java.util.HashMap; + +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.TimeStamp; + +/** + * + * Describe a raw Data Packet, this is how a packet is + * received from the network and how it will be transmitted. It + * essentially wraps the raw bytestream + * + */ +public class RawPacket { + private byte[] packetData; + private LinkEncap encap; + private TimeStamp incomingTime; + private TimeStamp copyTime; + private Map props; + private NodeConnector incomingNodeConnector; + private NodeConnector outgoingNodeConnector; + + /** + * If the packet is being sent this parameter tells where the + * packet is sent toward + * + * + * @return the NodeConnector toward where the packet is being sent + */ + public NodeConnector getOutgoingNodeConnector() { + return outgoingNodeConnector; + } + + /** + * Setter method for OutGoing NodeConnector + * + * @param outgoingNodeConnector NodeConnector toward where the + * packet is travelling + */ + public void setOutgoingNodeConnector(NodeConnector outgoingNodeConnector) { + this.outgoingNodeConnector = outgoingNodeConnector; + } + + /** + * Return the incoming NodeConnector if the packet was received + * + * @return NodeConnector where the packet was received from + */ + public NodeConnector getIncomingNodeConnector() { + return incomingNodeConnector; + } + + /** + * Setter for Incoming NodeConnector + * + * @param incomingNodeConnector NodeConnector to be used and incoming one + */ + public void setIncomingNodeConnector(NodeConnector incomingNodeConnector) { + this.incomingNodeConnector = incomingNodeConnector; + } + + /** + * Retrieve a given property attached to the packet, if exits of course + * + * @param key Key to retrieve the wanted property attached to the packet + * + * @return The property attached to the packet + */ + public Object getProps(Object key) { + if (this.props != null) { + return this.props.get(key); + } + return null; + } + + /** + * Generic data associated to the data packet + * + * @param key key for the association + * @param value value associated to the key + */ + public void setProps(Object key, Object value) { + if (this.props == null) { + this.props = new HashMap(); + } + + this.props.put(key, value); + } + + /** + * Constructor for RawPacket + * + * @param data content of the packet as bytestream + * @param e datalink encapsulation for the packet + * + */ + public RawPacket(byte[] data, LinkEncap e) throws ConstructionException { + if (data == null) { + throw new ConstructionException("Empty data"); + } + if (e == null) { + throw new ConstructionException("Encap not known"); + } + this.packetData = new byte[data.length]; + System.arraycopy(data, 0, this.packetData, 0, data.length); + this.encap = e; + this.incomingTime = new TimeStamp(System.currentTimeMillis(), + "IncomingTime"); + this.copyTime = null; + } + + /** + * Copy Constructor for RawPacket, it perform a copy of the packet + * so each packet can be modified indipendently without worrying + * that source packet content is touched + * + * @param src packet to copy data from + * + */ + public RawPacket(RawPacket src) throws ConstructionException { + if (src == null) { + throw new ConstructionException("null source packet"); + } + if (src.getPacketData() != null) { + this.packetData = new byte[src.getPacketData().length]; + System.arraycopy(src.getPacketData(), 0, this.packetData, 0, src + .getPacketData().length); + } else { + throw new ConstructionException("Empty packetData"); + } + this.encap = src.getEncap(); + this.incomingTime = src.getIncomingTime(); + this.incomingNodeConnector = src.getIncomingNodeConnector(); + this.outgoingNodeConnector = src.getOutgoingNodeConnector(); + this.props = (src.props == null ? null : new HashMap(src.props)); + this.copyTime = new TimeStamp(System.currentTimeMillis(), "CopyTime"); + } + + /** + * Constructor for RawPacket with Ethernet encapsulation + * + * @param data content of the packet as bytestream + * + */ + public RawPacket(byte[] data) throws ConstructionException { + this(data, LinkEncap.ETHERNET); + } + + /** + * Read the timestamp when the packet has entered the system + * + * @return The timestamp when the packet has entered the system + */ + public TimeStamp getIncomingTime() { + return this.incomingTime; + } + + /** + * Read the packet encapsulation + * + * @return The encapsulation for the raw packet, necessary to + * start parsing the packet + */ + public LinkEncap getEncap() { + return this.encap; + } + + /** + * Get bytestream of the packet body + * + * @return The raw bytestream composing the packet + */ + public byte[] getPacketData() { + return this.packetData; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/TCP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/TCP.java new file mode 100644 index 0000000000..ca4a871683 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/TCP.java @@ -0,0 +1,246 @@ + +/* + * 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.controller.sal.packet; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +/** + * Class that represents the TCP segment objects + * + * + */ +public class TCP extends Packet { + + private static final String SRCPORT = "SourcePort"; + private static final String DESTPORT = "DestinationPort"; + private static final String SEQNUMBER = "SequenceNumber"; + private static final String ACKNUMBER = "AcknoledgementNumber"; + private static final String DATAOFFSET = "DataOffset"; + private static final String RESERVED = "Reserved"; + private static final String HEADERLENFLAGS = "HeaderLenFlags"; + private static final String WINDOWSIZE = "WindowSize"; + private static final String CHECKSUM = "Checksum"; + private static final String URGENTPOINTER = "UrgentPointer"; + + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + { + put(SRCPORT, new ImmutablePair(0, 16)); + put(DESTPORT, new ImmutablePair(16, 16)); + put(SEQNUMBER, new ImmutablePair(32, 32)); + put(ACKNUMBER, new ImmutablePair(64, 32)); + put(DATAOFFSET, new ImmutablePair(96, 4)); + put(RESERVED, new ImmutablePair(100, 3)); + put(HEADERLENFLAGS, new ImmutablePair(103, 9)); + put(WINDOWSIZE, new ImmutablePair(112, 16)); + put(CHECKSUM, new ImmutablePair(128, 16)); + put(URGENTPOINTER, new ImmutablePair(144, 16)); + } + }; + + private Map fieldValues; + + /** + * Default constructor that sets all the header fields to zero + */ + public TCP() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + /* Setting all remaining header field values to + * default value of 0. These maybe changed as needed + */ + setSourcePort((short) 0); + setDestinationPort((short) 0); + setSequenceNumber(0); + setAckNumber(0); + setDataOffset((byte) 0); + setReserved((byte) 0); + setWindowSize((short) 0); + setUrgentPointer((short) 0); + setChecksum((short) 0); + } + + /** + * Constructor that sets the access level for the packet and + * sets all the header fields to zero. + */ + public TCP(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + /* Setting all remaining header field values to + * default value of 0. These maybe changed as needed + */ + setSourcePort((short) 0); + setDestinationPort((short) 0); + setSequenceNumber(0); + setAckNumber(0); + setDataOffset((byte) 0); + setReserved((byte) 0); + setWindowSize((short) 0); + setUrgentPointer((short) 0); + setChecksum((short) 0); + } + + @Override + /** + * Stores the value read from data stream + */ + public void setHeaderField(String headerField, byte[] readValue) { + hdrFieldsMap.put(headerField, readValue); + } + + /** + * Sets the TCP source port for the current TCP object instance + * @param short tcpSourcePort + * @return TCP + */ + public TCP setSourcePort(short tcpSourcePort) { + byte[] sourcePort = BitBufferHelper.toByteArray(tcpSourcePort); + fieldValues.put(SRCPORT, sourcePort); + return this; + } + + /** + * Sets the TCP destination port for the current TCP object instance + * @param short tcpDestinationPort + * @return TCP + */ + public TCP setDestinationPort(short tcpDestinationPort) { + byte[] destinationPort = BitBufferHelper + .toByteArray(tcpDestinationPort); + fieldValues.put(DESTPORT, destinationPort); + return this; + } + + /** + * Sets the TCP sequence number for the current TCP object instance + * @param int tcpSequenceNumber + * @return TCP + */ + public TCP setSequenceNumber(int tcpSequenceNumber) { + byte[] sequenceNumber = BitBufferHelper.toByteArray(tcpSequenceNumber); + fieldValues.put(SEQNUMBER, sequenceNumber); + return this; + } + + /** + * Sets the TCP data offset for the current TCP object instance + * @param byte tcpDataOffset + * @return TCP + */ + public TCP setDataOffset(byte tcpDataOffset) { + byte[] offset = BitBufferHelper.toByteArray(tcpDataOffset); + fieldValues.put("DataOffset", offset); + return this; + } + + /** + * Sets the TCP reserved bits for the current TCP object instance + * @param byte tcpReserved + * @return TCP + */ + public TCP setReserved(byte tcpReserved) { + byte[] reserved = BitBufferHelper.toByteArray(tcpReserved); + fieldValues.put("Reserved", reserved); + return this; + } + + /** + * Sets the TCP Ack number for the current TCP object instance + * @param int tcpAckNumber + * @return TCP + */ + public TCP setAckNumber(int tcpAckNumber) { + byte[] ackNumber = BitBufferHelper.toByteArray(tcpAckNumber); + fieldValues.put(ACKNUMBER, ackNumber); + return this; + } + + /** + * Sets the TCP flags for the current TCP object instance + * @param short tcpFlags + * @return TCP + */ + public TCP setHeaderLenFlags(short tcpFlags) { + byte[] headerLenFlags = BitBufferHelper.toByteArray(tcpFlags); + fieldValues.put(HEADERLENFLAGS, headerLenFlags); + return this; + } + + /** + * Sets the TCP window size for the current TCP object instance + * @param short tcpWsize + * @return TCP + */ + public TCP setWindowSize(short tcpWsize) { + byte[] wsize = BitBufferHelper.toByteArray(tcpWsize); + fieldValues.put(WINDOWSIZE, wsize); + return this; + } + + /** + * Sets the TCP checksum for the current TCP object instance + * @param short tcpChecksum + * @return TCP + */ + public TCP setChecksum(short tcpChecksum) { + byte[] checksum = BitBufferHelper.toByteArray(tcpChecksum); + fieldValues.put(CHECKSUM, checksum); + return this; + } + + /** + * Sets the TCP Urgent Pointer for the current TCP object instance + * @param short tcpUrgentPointer + * @return TCP + */ + public TCP setUrgentPointer(short tcpUrgentPointer) { + byte[] urgentPointer = BitBufferHelper.toByteArray(tcpUrgentPointer); + fieldValues.put(URGENTPOINTER, urgentPointer); + return this; + } + + /** + * Gets the stored source port value of TCP header + * @return the sourcePort + */ + public short getSourcePort() { + return (BitBufferHelper.getShort(fieldValues.get(SRCPORT))); + } + + /** + * Gets the stored destination port value of TCP header + * @return the destinationPort + */ + public short getDestinationPort() { + return (BitBufferHelper.getShort(fieldValues.get(DESTPORT))); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/UDP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/UDP.java new file mode 100644 index 0000000000..52827d55c6 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/UDP.java @@ -0,0 +1,176 @@ + +/* + * 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.controller.sal.packet; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +/** + * Class that represents the UDP datagram objects + * + * + */ + +public class UDP extends Packet { + + private static final String SRCPORT = "SourcePort"; + private static final String DESTPORT = "DestinationPort"; + private static final String LENGTH = "Length"; + private static final String CHECKSUM = "Checksum"; + + private static Map> fieldCoordinates = new LinkedHashMap>() { + private static final long serialVersionUID = 1L; + { + put(SRCPORT, new ImmutablePair(0, 16)); + put(DESTPORT, new ImmutablePair(16, 16)); + put(LENGTH, new ImmutablePair(32, 16)); + put(CHECKSUM, new ImmutablePair(48, 16)); + } + }; + + public UDP() { + super(); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + /* Setting all remaining header field values to + * default value of 0. These maybe changed as needed + */ + setSourcePort((short) 0); + setDestinationPort((short) 0); + setChecksum((short) 0); + } + + public UDP(boolean writeAccess) { + super(writeAccess); + fieldValues = new HashMap(); + hdrFieldCoordMap = fieldCoordinates; + hdrFieldsMap = fieldValues; + /* Setting all remaining header field values to + * default value of 0. These maybe changed as needed + */ + setSourcePort((short) 0); + setDestinationPort((short) 0); + setChecksum((short) 0); + } + + private Map fieldValues; + + /* public static Map> decodeMap; + + static { + decodeMap = new HashMap>(); + UDP.decodeMap.put((short)67, DHCP.class); + UDP.decodeMap.put((short)68, DHCP.class); + }*/ + /** + * Get the stored source port + * @return short - the sourcePort + */ + public short getSourcePort() { + return (BitBufferHelper.getShort(fieldValues.get(SRCPORT))); + } + + /** + * Get the stored destination port + * @return short - the destinationPort + */ + public short getDestinationPort() { + return (BitBufferHelper.getShort(fieldValues.get(DESTPORT))); + } + + /** + * Gets the stored length of UDP header + * @return short - the length + */ + public short getLength() { + return (BitBufferHelper.getShort(fieldValues.get(LENGTH))); + } + + /** + * Get the stored checksum value of the UDP header + * @return short - the checksum + */ + public short getChecksum() { + return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM))); + } + + @Override + /** + * Store the value read from data stream in hdrFieldMap + */ + public void setHeaderField(String headerField, byte[] readValue) { + /*if (headerField.equals("Protocol")) { + payloadClass = decodeMap.get(readValue); + }*/ + hdrFieldsMap.put(headerField, readValue); + } + + /** + * Sets the sourcePort value for the current UDP object instance + * @param short - the sourcePort to set + * @return UDP + */ + public UDP setSourcePort(short udpSourcePort) { + byte[] sourcePort = BitBufferHelper.toByteArray(udpSourcePort); + fieldValues.put(SRCPORT, sourcePort); + return this; + } + + /** + * Sets the destinationPort value for the current UDP object instance + * @param short - the destinationPort to set + * @return UDP + */ + public UDP setDestinationPort(short udpDestinationPort) { + byte[] destinationPort = BitBufferHelper + .toByteArray(udpDestinationPort); + fieldValues.put(DESTPORT, destinationPort); + return this; + } + + /** + * Set the UDP header length value for the current UDP object instance + * @param short - the length to set + * @return UDP + */ + public UDP setLength(short udpLength) { + byte[] length = BitBufferHelper.toByteArray(udpLength); + fieldValues.put(LENGTH, length); + return this; + } + + /** + * Set the checksum for the current UDP object instance + * @param short - the checksum to set + * @return UDP + */ + public UDP setChecksum(short udpChecksum) { + byte[] checksum = BitBufferHelper.toByteArray(udpChecksum); + fieldValues.put(CHECKSUM, checksum); + return this; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/address/DataLinkAddress.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/address/DataLinkAddress.java new file mode 100644 index 0000000000..433f64c215 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/address/DataLinkAddress.java @@ -0,0 +1,87 @@ + +/* + * 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.controller.sal.packet.address; + +import java.io.Serializable; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSeeAlso; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * @file DataLinkAddress.java + * + * @brief Abstract base class for a Datalink Address + * + */ + +/** + * Abstract base class for a Datalink Address + * + */ +@XmlRootElement +@XmlSeeAlso( { EthernetAddress.class }) +abstract public class DataLinkAddress implements Serializable { + private static final long serialVersionUID = 1L; + private String name; + + public DataLinkAddress() { + + } + + /** + * Constructor of super class + * + * @param name Create a new DataLink, not for general use but + * available only for sub classes + * + * @return constructed object + */ + protected DataLinkAddress(String name) { + this.name = name; + } + + /** + * Used to copy the DataLinkAddress in a polymorphic way + * + * + * @return A clone of this DataLinkAddress + */ + abstract public DataLinkAddress clone(); + + /** + * Allow to distinguish among different data link addresses + * + * + * @return Name of the DataLinkAdress we are working on + */ + public String getName() { + return this.name; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "DataLinkAddress[" + ReflectionToStringBuilder.toString(this) + + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/address/EthernetAddress.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/address/EthernetAddress.java new file mode 100644 index 0000000000..57dea9c3d9 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/address/EthernetAddress.java @@ -0,0 +1,114 @@ + +/* + * 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.controller.sal.packet.address; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.utils.HexEncode; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class EthernetAddress extends DataLinkAddress { + private static final long serialVersionUID = 1L; + private byte[] macAddress; + + public static final EthernetAddress BROADCASTMAC = createWellKnownAddress(new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff }); + + public static final EthernetAddress INVALIDHOST = BROADCASTMAC; + + public static final String addressName = "Ethernet MAC Address"; + public static final int SIZE = 6; + + private static final EthernetAddress createWellKnownAddress(byte[] mac) { + try { + return new EthernetAddress(mac); + } catch (ConstructionException ce) { + return null; + } + } + + /* Private constructor to satisfy JAXB */ + private EthernetAddress() { + + } + + /** + * Public constructor for an Ethernet MAC address starting from + * the byte constituing the address, the constructor validate the + * size of the arrive to make sure it met the expected size + * + * @param macAddress A byte array in big endian format + * representing the Ethernet MAC Address + * + * @return The constructed object if valid + */ + public EthernetAddress(byte[] macAddress) throws ConstructionException { + super(addressName); + + if (macAddress == null) { + throw new ConstructionException("Null input parameter passed"); + } + + if (macAddress.length != SIZE) { + throw new ConstructionException( + "Wrong size of passed byte array, expected:" + SIZE + + " got:" + macAddress.length); + } + this.macAddress = new byte[SIZE]; + System.arraycopy(macAddress, 0, this.macAddress, 0, SIZE); + } + + public EthernetAddress clone() { + try { + return new EthernetAddress(this.macAddress.clone()); + } catch (ConstructionException ce) { + return null; + } + } + + /** + * Return the Ethernet Mac address in byte array format + * + * @return The Ethernet Mac address in byte array format + */ + public byte[] getValue() { + return this.macAddress; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public String toString() { + return "EthernetAddress[" + ReflectionToStringBuilder.toString(this) + + "]"; + } + + @XmlElement(name = "macAddress") + public String getMacAddress() { + return HexEncode.bytesToHexString(macAddress); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/FlowOnNode.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/FlowOnNode.java new file mode 100644 index 0000000000..431f589563 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/FlowOnNode.java @@ -0,0 +1,119 @@ + +/* + * 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.controller.sal.reader; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.opendaylight.controller.sal.flowprogrammer.Flow; + +/** + * Represents the flow that is installed on the network node + * along with the table location, hit counters and timers + */ + +@XmlRootElement (name="FlowStat") +@XmlAccessorType(XmlAccessType.NONE) +public class FlowOnNode { + @XmlElement + private Flow flow; // Flow descriptor + @XmlElement + private byte tableId; + @XmlElement + private int durationSeconds; + @XmlElement + private int durationNanoseconds; + @XmlElement + private long packetCount; + @XmlElement + private long byteCount; + + /* Dummy constructor for JAXB */ + private FlowOnNode () { + } + + public FlowOnNode(Flow flow) { + this.flow = flow; + } + + /** + * Returns the description of the flow which statistics are about + * @return + */ + public Flow getFlow() { + return flow; + } + + /** + * Set the packet count's value + * @param count + */ + public void setPacketCount(long count) { + packetCount = count; + } + + /** + * Set the byte count's value + * @param count + */ + public void setByteCount(long count) { + byteCount = count; + } + + /** + * Returns the packet count for the flow + * @return + */ + public long getPacketCount() { + return packetCount; + } + + /** + * Return the byte count for the flow + * @return + */ + public long getByteCount() { + return byteCount; + } + + public byte getTableId() { + return tableId; + } + + public void setTableId(byte tableId) { + this.tableId = tableId; + } + + public int getDurationSeconds() { + return durationSeconds; + } + + public void setDurationSeconds(int durationSeconds) { + this.durationSeconds = durationSeconds; + } + + public int getDurationNanoseconds() { + return durationNanoseconds; + } + + public void setDurationNanoseconds(int durationNanoseconds) { + this.durationNanoseconds = durationNanoseconds; + } + + @Override + public String toString() { + return "FlowOnNode[flow =" + flow + ", tableId = " + tableId + + ", sec = " + durationSeconds + ", nsec = " + + durationNanoseconds + ", pkt = " + packetCount + ", byte = " + + byteCount + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/IPluginInReadService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/IPluginInReadService.java new file mode 100644 index 0000000000..c563037f1e --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/IPluginInReadService.java @@ -0,0 +1,72 @@ + +/* + * 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.controller.sal.reader; + +import java.util.List; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.flowprogrammer.Flow; + +/** + * @file IPluginInReadService.java + * + * @brief Hardware view interface to be implemented by protocol plugins + * + * + * + */ +public interface IPluginInReadService { + + /** + * Returns the hardware image for the specified flow on the specified network node + * @param node + * @param flow + * @return + */ + public FlowOnNode readFlow(Node node, Flow flow, boolean cached); + + /** + * Returns the hardware view of all the flow installed on the specified network node + * @param node + * @return + */ + public List readAllFlow(Node node, boolean cached); + + /** + * Returns the description of the network node as provided by the node itself + * @param node + * @return + */ + public NodeDescription readDescription(Node node, boolean cached); + + /** + * Returns the hardware view of the specified network node connector + * @param node + * @return + */ + public NodeConnectorStatistics readNodeConnector(NodeConnector connector, + boolean cached); + + /** + * Returns the hardware info for all the node connectors on the specified network node + * @param node + * @return + */ + public List readAllNodeConnector(Node node, + boolean cached); + + /** + * Returns the averaged transmit rate for the specified node connector + * @param connector + * @return tx rate [bps] + */ + public long getTransmitRate(NodeConnector connector); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/IReadService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/IReadService.java new file mode 100644 index 0000000000..3a9f828d94 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/IReadService.java @@ -0,0 +1,117 @@ + +/* + * 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.controller.sal.reader; + +import java.util.List; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.flowprogrammer.Flow; + +/** + * Interface for retrieving the network node's flow/port/queue hardware view + * + * + * + */ +public interface IReadService { + /** + * Get the hardware view for the specified flow on the specified network node + * + * @param node + * @param flow + */ + FlowOnNode readFlow(Node node, Flow flow); + + /** + * Get the hardware view for the specified flow on the specified network node + * This call results in a direct polling of the information from the node + * Caller will be blocked until node replies or request times out + * + * @param node + * @param flow + */ + FlowOnNode nonCachedReadFlow(Node node, Flow flow); + + /** + * Get the hardware view for all the flows installed on the network node + * + * @param node + * @return + */ + List readAllFlows(Node node); + + /** + * Get the hardware view for all the flows installed on the network node + * This call results in a direct polling of the information from the node + * Caller will be blocked until node replies or request times out + * + * @param node + * @param flow + */ + List nonCachedReadAllFlows(Node node); + + /** + * Get the description information for the network node + * @param node + * @return + */ + NodeDescription readDescription(Node node); + + /** + * Get the description information for the network node + * This call results in a direct polling of the information from the node + * Caller will be blocked until node replies or request times out + * + * @param node + * @return + */ + NodeDescription nonCachedReadDescription(Node node); + + /** + * Get the hardware view for the specified node connector + * @param connector + */ + NodeConnectorStatistics readNodeConnector(NodeConnector connector); + + /** + * Get the hardware view for all the node connectors + * present on the specified network node + * @param connector + */ + List readNodeConnectors(Node node); + + /** + * Get the node connectors statistics information for the network node + * This call results in a direct polling of the information from the node + * Caller will be blocked until node replies or request times out + * + * @param node + * @return + */ + List nonCachedReadNodeConnectors(Node node); + + /** + * Get the node connectors statistics information for the network node + * + * @param node + * @return + */ + NodeConnectorStatistics nonCachedReadNodeConnector(NodeConnector connector); + + /** + * Get the transmit rate for the specified node connector + * + * @param connector + * @return tx rate [bps] + */ + long getTransmitRate(NodeConnector connector); + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeConnectorStatistics.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeConnectorStatistics.java new file mode 100644 index 0000000000..a8c83e7913 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeConnectorStatistics.java @@ -0,0 +1,282 @@ + +/* + * 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.controller.sal.reader; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.opendaylight.controller.sal.core.NodeConnector; + +/** + * Represents the statistics for the node conenctor + * + * + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class NodeConnectorStatistics { + @XmlElement + private NodeConnector nodeConnector; + @XmlElement + private long receivePackets; + @XmlElement + private long transmitPackets; + @XmlElement + private long receiveBytes; + @XmlElement + private long transmitBytes; + @XmlElement + private long receiveDrops; + @XmlElement + private long transmitDrops; + @XmlElement + private long receiveErrors; + @XmlElement + private long transmitErrors; + @XmlElement + private long receiveFrameError; + @XmlElement + private long receiveOverRunError; + @XmlElement + private long receiveCrcError; + @XmlElement + private long collisionCount; + + //To Satisfy JAXB + public NodeConnectorStatistics() { + + } + /** + * Set the node connector + * @param port + */ + public void setNodeConnector(NodeConnector port) { + this.nodeConnector = port; + } + + /** + * Returns the node connector + * @return + */ + public NodeConnector getNodeConnector() { + return nodeConnector; + } + + /** + * Set the rx packet count's value + * @param count + */ + public void setReceivePacketCount(long count) { + receivePackets = count; + } + + /** + * Returns the rx packet count for the port + * @return + */ + public long getReceivePacketCount() { + return receivePackets; + } + + /** + * Set the tx packet count's value + * @param count + */ + public void setTransmitPacketCount(long count) { + transmitPackets = count; + } + + /** + * Returns the tx packet count for the port + * @return + */ + public long getTransmitPacketCount() { + return transmitPackets; + } + + /** + * Set the rx byte count's value + * @param count + */ + public void setReceiveByteCount(long count) { + receiveBytes = count; + } + + /** + * Return the rx byte count for the port + * @return + */ + public long getReceiveByteCount() { + return receiveBytes; + } + + /** + * Set the tx byte count's value + * @param count + */ + public void setTransmitByteCount(long count) { + transmitBytes = count; + } + + /** + * Return the tx byte count for the port + * @return + */ + public long getTransmitByteCount() { + return transmitBytes; + } + + /** + * Set the rx drop count's value + * @param count + */ + public void setReceiveDropCount(long count) { + receiveDrops = count; + } + + /** + * Returns the rx drop count for the port + * @return + */ + public long getReceiveDropCount() { + return receiveDrops; + } + + /** + * Set the tx drop count's value + * @param count + */ + public void setTransmitDropCount(long count) { + transmitDrops = count; + } + + /** + * Returns the tx drop count for the port + * @return + */ + public long getTransmitDropCount() { + return transmitDrops; + } + + /** + * Set the rx error count's value + * @param count + */ + public void setReceiveErrorCount(long count) { + receiveErrors = count; + } + + /** + * Return the rx error count for the port + * @return + */ + public long getReceiveErrorCount() { + return receiveErrors; + } + + /** + * Set the tx error count's value + * @param count + */ + public void setTransmitErrorCount(long count) { + transmitErrors = count; + } + + /** + * Return the tx error count for the port + * @return + */ + public long getTransmitErrorCount() { + return transmitErrors; + } + + /** + * Set the rx frame error value + * @param count + */ + public void setReceiveFrameErrorCount(long count) { + receiveFrameError = count; + } + + /** + * Returns the rx frame error for the port + * @return + */ + public long getReceiveFrameErrorCount() { + return receiveFrameError; + } + + /** + * Set the rx overrun error value + * @param count + */ + public void setReceiveOverRunErrorCount(long count) { + receiveOverRunError = count; + } + + /** + * Return the rx overrun error for the port + * @return + */ + public long getReceiveOverRunErrorCount() { + return receiveOverRunError; + } + + /** + * Set the rx CRC Error value + * @param count + */ + public void setReceiveCRCErrorCount(long count) { + receiveCrcError = count; + } + + /** + * Return the rx CRC error for the port + * @return + */ + public long getReceiveCRCErrorCount() { + return receiveCrcError; + } + + /** + * Set the collisionCount count's value + * @param count + */ + public void setCollisionCount(long count) { + collisionCount = count; + } + + /** + * Return the collisionCount count for the port + * @return + */ + public long getCollisionCount() { + return collisionCount; + } + + @Override + public String toString() { + return "NodeConnectorStats[portNumber = " + nodeConnector + + ", receivePackets = " + receivePackets + + ", transmitPackets = " + transmitPackets + + ", receiveBytes = " + receiveBytes + ", transmitBytes = " + + transmitBytes + ", receiveDrops = " + receiveDrops + + ", transmitDrops = " + transmitDrops + ", receiveErrors = " + + receiveErrors + ", transmitErrors = " + transmitErrors + + ", receiveFrameError = " + receiveFrameError + + ", receiveOverRunError = " + receiveOverRunError + + ", receiveCrcError = " + receiveCrcError + + ", collisionCount = " + collisionCount + "]"; + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeDescription.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeDescription.java new file mode 100644 index 0000000000..b68326707d --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/NodeDescription.java @@ -0,0 +1,76 @@ + +/* + * 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.controller.sal.reader; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * Represents the switch description information + * + * + * + */ +public class NodeDescription { + private String manufacturer; + private String hardware; + private String software; + private String serialNumber; + private String sdnProtocolDescription; + + public NodeDescription() { + + } + + public String getManufacturer() { + return manufacturer; + } + + public void setManufacturer(String manufacturer) { + this.manufacturer = manufacturer; + } + + public String getHardware() { + return hardware; + } + + public void setHardware(String hardware) { + this.hardware = hardware; + } + + public String getSoftware() { + return software; + } + + public void setSoftware(String software) { + this.software = software; + } + + public String getSerialNumber() { + return serialNumber; + } + + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + } + + public String getSdnProtocolDescription() { + return sdnProtocolDescription; + } + + public void setSdnProtocolDescription(String sdnProtocolDescription) { + this.sdnProtocolDescription = sdnProtocolDescription; + } + + @Override + public String toString() { + return "HwDescription[" + ReflectionToStringBuilder.toString(this) + + "]"; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/routing/IListenRoutingUpdates.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/routing/IListenRoutingUpdates.java new file mode 100644 index 0000000000..dde65108b1 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/routing/IListenRoutingUpdates.java @@ -0,0 +1,26 @@ + +/* + * 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.controller.sal.routing; + +/** + * Interface that will be implemented by the modules that wants to + * know events published by the routing engine + * + */ + +public interface IListenRoutingUpdates { + /** + * Method invoked when the recalculation of the all shortest path + * tree is done + * + */ + public void recalculateDone(); + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/routing/IRouting.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/routing/IRouting.java new file mode 100644 index 0000000000..6d246c6d23 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/routing/IRouting.java @@ -0,0 +1,63 @@ + +/* + * 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.controller.sal.routing; + +import java.util.Map; + +import org.opendaylight.controller.sal.core.Edge; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.Path; + +public interface IRouting { + + /** + * Returns a Path leading from the source to the destination + * @param src: source Node + * @param dst: destination Node + * @return: Path + */ + public Path getRoute(Node src, Node dst); + + /** + * Returns a Max ThroughPut Path leading from the source to the destination + * @param src: source Node + * @param dst: destination Node + * @return: MTPath + */ + public Path getMaxThroughputRoute(Node src, Node dst); + + /** + * Returns a Path leading from the source to the destination that meets the specified bandwidth + * @param src: source Node + * @param dst: destination Node + * @param Bw: bandwidth + * @return: Path + */ + public Path getRoute(Node src, Node dst, Short Bw); + + /** + * Remove all routes and reset all state. USE CAREFULLY! + */ + public void clear(); + + /** + * Remove all Max Throughput Routes and reset all state. USE CAREFULLY! + */ + public void clearMaxThroughput(); + + /** + * Initialization For Max Throughput + * @param EdgeWeightMap: Map containing Edge and Corresponding + * Weight. Optional Param - if null, implementation specific weight + * calculation will be used. + */ + public void initMaxThroughput(Map EdgeWeightMap); + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IListenTopoUpdates.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IListenTopoUpdates.java new file mode 100644 index 0000000000..8a640f1e9b --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IListenTopoUpdates.java @@ -0,0 +1,58 @@ + +/* + * 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.controller.sal.topology; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.Edge; +import org.opendaylight.controller.sal.core.Property; +import org.opendaylight.controller.sal.core.UpdateType; + +/** + * @file IListenTopoUpdates.java + * + * @brief Topology notifications provided by SAL toward the application + * + * For example an application that wants to keep up to date with the + * updates coming from SAL it will register in the OSGi service + * registry this interface (on a per-container base) and SAL will call it + * providing the update + */ + +/** + * Topology notifications provided by SAL toward the application + * + */ +public interface IListenTopoUpdates { + /** + * Called to update on Edge in the topology graph + * + * @param e Edge being updated + * @param type Type of update + * @param props Properties of the edge, like BandWidth and/or Latency etc. + */ + public void edgeUpdate(Edge e, UpdateType type, Set props); + + /** + * Called when an Edge utilization is above the safety threshold + * configured on the controller + * + * @param edge The edge which bandwidth usage is above the safety level + */ + public void edgeOverUtilized(Edge edge); + + /** + * Called when the Edge utilization is back to normal, below the safety + * threshold level configured on the controller + * + * @param edge + */ + public void edgeUtilBackToNormal(Edge edge); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IPluginInTopologyService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IPluginInTopologyService.java new file mode 100644 index 0000000000..3744d8099f --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IPluginInTopologyService.java @@ -0,0 +1,36 @@ + +/* + * 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.controller.sal.topology; + +/** + * @file IPluginInTopologyService.java + * + * @brief Methods that are invoked from SAL toward the protocol + * plugin. + * + * For example if SAL startup late in respect to a protocol plugin, or + * restarts, we need away to sollicit the push of older updates from + * Protocol Plugins this interface serve the purpose. This a practical + * example of the type of service provided by this interface + */ + +/** + * Methods that are invoked from SAL toward the protocol + * plugin to sollicit Topoloy updates + * + */ +public interface IPluginInTopologyService { + /** + * Tell to protocol plugin that is time to send the updates of the + * current topology because someone joined late the game + * + */ + public void sollicitRefresh(); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IPluginOutTopologyService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IPluginOutTopologyService.java new file mode 100644 index 0000000000..7ea9360300 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/IPluginOutTopologyService.java @@ -0,0 +1,56 @@ + +/* + * 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.controller.sal.topology; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.Edge; +import org.opendaylight.controller.sal.core.Property; +import org.opendaylight.controller.sal.core.UpdateType; + +/** + * @file IPluginOutTopologyService.java + * + * @brief Methods that are invoked from Protocol Plugin toward SAL + * + * Every time a protocol plugin update the topology, it will call this + * service provided by SAL so the update can migrate upward toward the + * applications + */ + +/** + * Methods that are invoked from Protocol Plugin toward SAL + * + */ +public interface IPluginOutTopologyService { + /** + * Called to update on Edge in the topology graph + * + * @param e Edge being updated + * @param type Type of update + * @param props Properties of the edge, like BandWidth and/or Latency etc. + */ + public void edgeUpdate(Edge e, UpdateType type, Set props); + + /** + * Called when an Edge utilization is above the safety threshold + * configured on the controller + * @param edge + */ + public void edgeOverUtilized(Edge edge); + + /** + * Called when the Edge utilization is back to normal, below the safety + * threshold level configured on the controller + * + * @param edge + */ + public void edgeUtilBackToNormal(Edge edge); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/ITopologyService.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/ITopologyService.java new file mode 100644 index 0000000000..c9b7a0189e --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/topology/ITopologyService.java @@ -0,0 +1,32 @@ + +/* + * 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.controller.sal.topology; + +/** + * @file ITopologyService.java + * + * @brief Topology methods provided by SAL toward the applications + * + * For example An application that startup late in the game or restart + * for example, wants to know the current status of SAL, so can use + * this interface to get a bunlk sync of the topology status. + */ + +/** + * Topology methods provided by SAL toward the applications + */ +public interface ITopologyService { + /** + * Tell to SAL that is time to send the updates of the + * current topology because someone joined late the game + * + */ + public void sollicitRefresh(); +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ConfigurationObject.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ConfigurationObject.java new file mode 100644 index 0000000000..2e0009cd47 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ConfigurationObject.java @@ -0,0 +1,14 @@ + +/* + * 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.controller.sal.utils; + +public interface ConfigurationObject { + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Direction.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Direction.java new file mode 100644 index 0000000000..8541210614 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Direction.java @@ -0,0 +1,31 @@ + +/* + * 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.controller.sal.utils; + +import java.io.Serializable; + +/** + * Direction enum + * + * + * + */ +public enum Direction implements Serializable { + FORWARD("forward"), REVERSE("reverse"); + private Direction(String name) { + this.name = name; + } + + private String name; + + public String toString() { + return name; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/EtherTypes.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/EtherTypes.java new file mode 100644 index 0000000000..dbdadffe34 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/EtherTypes.java @@ -0,0 +1,117 @@ + +/* + * 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.controller.sal.utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * The enum contains the most common 802.3 ethernet types and 802.2 + SNAP protocol ids + * + * + * + */ +public enum EtherTypes { + PVSTP("PVSTP", 0x010B), // 802.2 + SNAP (Spanning Tree) + CDP("CDP", 0x2000), // 802.2 + SNAP + VTP("VTP", 0x2003), // 802.2 + SNAP + IPv4("IPv4", 0x800), ARP("ARP", 0x806), RARP("Reverse ARP", 0x8035), VLANTAGGED( + "VLAN Tagged", 0x8100), // 802.1Q + IPv6("IPv6", 0x86DD), MPLSUCAST("MPLS Unicast", 0x8847), MPLSMCAST( + "MPLS Multicast", 0x8848), QINQ("QINQ", 0x88A8), // Standard 802.1ad QinQ + LLDP("LLDP", 0x88CC), OLDQINQ("Old QINQ", 0x9100), // Old non-standard QinQ + CISCOQINQ("Cisco QINQ", 0x9200); // Cisco non-standard QinQ + + private static final String regexNumberString = "^[0-9]+$"; + private String description; + private int number; + + private EtherTypes(String description, int number) { + this.description = description; + this.number = number; + } + + public String toString() { + return description; + } + + public int intValue() { + return number; + } + + public short shortValue() { + return ((Integer) number).shortValue(); + } + + public static String getEtherTypeName(int number) { + return getEtherTypeInternal(number); + } + + public static String getEtherTypeName(short number) { + return getEtherTypeInternal((int) number & 0xffff); + } + + public static String getEtherTypeName(byte number) { + return getEtherTypeInternal((int) number & 0xff); + } + + private static String getEtherTypeInternal(int number) { + for (EtherTypes type : EtherTypes.values()) { + if (type.number == number) { + return type.toString(); + } + } + return "0x" + Integer.toHexString(number); + } + + public static short getEtherTypeNumberShort(String name) { + if (name.matches(regexNumberString)) { + return Short.valueOf(name); + } + for (EtherTypes type : EtherTypes.values()) { + if (type.description.equalsIgnoreCase(name)) { + return type.shortValue(); + } + } + return 0; + } + + public static int getEtherTypeNumberInt(String name) { + if (name.matches(regexNumberString)) { + return Integer.valueOf(name); + } + for (EtherTypes type : EtherTypes.values()) { + if (type.description.equalsIgnoreCase(name)) { + return type.intValue(); + } + } + return 0; + } + + public static List getEtherTypesNameList() { + List ethertypesList = new ArrayList(); + for (EtherTypes type : EtherTypes.values()) { + ethertypesList.add(type.toString()); + } + return ethertypesList; + } + + public static EtherTypes loadFromString(String string) { + int intType = Integer.parseInt(string); + + for (EtherTypes type : EtherTypes.values()) { + if (type.number == intType) { + return type; + } + } + return null; + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/GUIField.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/GUIField.java new file mode 100644 index 0000000000..9ebf8a2227 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/GUIField.java @@ -0,0 +1,48 @@ + +/* + * 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.controller.sal.utils; + +/** + * GUI field constants + * + * + * + */ +public enum GUIField { + USER("User"), PASSWORD("Password"), ROLE("Role"), SERVERIP("Server address"), SERVERSECRET( + "Server secret"), SERVERPROTOCOL("Server protocol"), NAME("Name"), CONTAINER( + "Container"), SUBNET("Subnet"), GATEWAYIP("Gateway IP Address/Mask"), NODE( + "Node"), NODEID("Node ID"), NODEMAC("Node MAC Address"), NODENAME( + "Node Name"), SRCNODE("Source Node"), DSTNODE("Destination Node"), SRCPORT( + "Source Port"), DSTPORT("Destination Port"), PORTS("Ports"), NODEPORTS( + "Node/Ports"), SPANPORTS("Span Ports"), TIER("Tier"), MODE("Mode"), INPUTPORT( + "Input Port"), ETHERTYPE("Ether Type"), DLSRCADDRESS("Source MAC"), DLDSTADDRESS( + "Dest MAC"), VLANID("Vlan Id"), VLANPRIO("Vlan Priority"), NWSRCADDRESS( + "Source IP"), NWDSTADDRESS("Dest IP"), NWPROTOCOL("Protocol"), NWPROTOCOLSHORT( + "Proto"), NWTOSBITS("TOS"), TPSRCPORT("Transport Source Port"), TPDSTPORT( + "Transport Dest Port"), TPSRCPORTSHORT("Source L4 Port"), TPDSTPORTSHORT( + "Dest L4 Port"), METRIC("Metric"), STATUS("Status"), TAG("Tag"), TAGS( + "Tags"), STATICVLAN("Static Vlan"), PRIORITY("Priority"), PORTGROUP( + "Port Group"), COOKIE("Cookie"), ACTIONS("Actions"), ACTIVE( + "Active"), IDLETIMEOUT("Idle Time Out"), HARDTIMEOUT( + "Hard Time Out"), INHARDWARE("Install on Switch"), STATICROUTE( + "Static Route"), NEXTHOPTYPE("NextHop Type"), NEXTHOP( + "NextHop address"); + + private GUIField(String name) { + this.name = name; + } + + private String name; + + public String toString() { + return name; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/GlobalConstants.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/GlobalConstants.java new file mode 100644 index 0000000000..abc0c23ae9 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/GlobalConstants.java @@ -0,0 +1,30 @@ + +/* + * 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.controller.sal.utils; + +/** + * Global Constants + * + */ +public enum GlobalConstants { + DEFAULT("default"), CONTAINERMANAGER("containermanager"), CONTAINERNAME( + "name"), STATICVLAN("staticvlan"), CLUSTERINGSERVICES("clusteringservices"), ONECONTROLLER( + "onecontroller"), STARTUPHOME("configuration/startup/"); + + private GlobalConstants(String name) { + this.name = name; + } + + private String name; + + public String toString() { + return name; + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/HexEncode.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/HexEncode.java new file mode 100644 index 0000000000..1cc2caca92 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/HexEncode.java @@ -0,0 +1,94 @@ + +/* + * 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.controller.sal.utils; + +import java.math.BigInteger; + +/** + * The class provides methods to convert hex encode strings + * + * + */ +public class HexEncode { + /** + * This method converts byte array into String format without ":" inserted. + */ + public static String bytesToHexString(byte[] bytes) { + int i; + String ret = ""; + String tmp; + StringBuffer buf = new StringBuffer(); + for (i = 0; i < bytes.length; i++) { + if (i > 0) + ret += ":"; + short u8byte = (short) ((short) bytes[i] & 0xff); + tmp = Integer.toHexString(u8byte); + if (tmp.length() == 1) + buf.append("0"); + buf.append(tmp); + } + ret = buf.toString(); + return ret; + } + + public static String longToHexString(long val) { + char arr[] = Long.toHexString(val).toCharArray(); + StringBuffer buf = new StringBuffer(); + // prepend the right number of leading zeros + int i = 0; + for (; i < (16 - arr.length); i++) { + buf.append("0"); + if ((i & 0x01) == 1) + buf.append(":"); + } + for (int j = 0; j < arr.length; j++) { + buf.append(arr[j]); + if ((((i + j) & 0x01) == 1) && (j < (arr.length - 1))) + buf.append(":"); + } + return buf.toString(); + } + + public static byte[] bytesFromHexString(String values) { + String[] octets = values.split(":"); + byte[] ret = new byte[octets.length]; + int i; + + for (i = 0; i < octets.length; i++) + ret[i] = Integer.valueOf(octets[i], 16).byteValue(); + return ret; + } + + public static long stringToLong(String values) { + long value = new BigInteger(values.replaceAll(":", ""), 16).longValue(); + return value; + } + + /** + * This method converts byte array into HexString format with ":" inserted. + */ + public static String bytesToHexStringWithColumn(byte[] bytes) { + int i; + String ret = ""; + String tmp; + StringBuffer buf = new StringBuffer(); + for (i = 0; i < bytes.length; i++) { + if (i > 0) + buf.append(":"); + short u8byte = (short) ((short) bytes[i] & 0xff); + tmp = Integer.toHexString(u8byte); + if (tmp.length() == 1) + buf.append("0"); + buf.append(tmp); + } + ret = buf.toString(); + return ret; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IObjectReader.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IObjectReader.java new file mode 100644 index 0000000000..af73dc7815 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IObjectReader.java @@ -0,0 +1,29 @@ + +/* + * 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.controller.sal.utils; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.ObjectInputStream; + +/** + * This interface is needed to allow object reconstruction when reading serialized objects from + * inside a package other than the one where ObjectReader is defined (otherwise you hit the + * java.lang.ClassNotFoundException). This interface will allow to deserialize a class from inside + * the package where the class is defined. All the exception handling can still happen in + * ObjectReader and the implementer of IObjectReader only need to throws such exceptions + * + * + * + */ +public interface IObjectReader { + public Object readObject(ObjectInputStream ois) + throws FileNotFoundException, IOException, ClassNotFoundException; +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IPProtocols.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IPProtocols.java new file mode 100644 index 0000000000..416018d98e --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IPProtocols.java @@ -0,0 +1,260 @@ + +/* + * 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.controller.sal.utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * It represents the most common IP protocols numbers + * It provides the binding between IP protocol names and numbers + * and provides APIs to read and parse them in either of the two forms + * + * + * + */ +// Openflow 1.0 supports the IP Proto match only for ICMP, TCP and UDP +public enum IPProtocols { + ANY("any", 0), + /* HOPOPT("HOPOPT",0), + */ICMP("ICMP", 1), + /* IGMP("IGMP",2), + GGP("GGP",3), + IPV4("IPv4",4), + ST("ST",5), + */TCP("TCP", 6), + /* CBT("CBT",7), + EGP("EGP",8), + IGP("IGP",9), + BBNRCCMON("BBN-RCC-MON",10), + NVPII("NVP-II",11), + PUP("PUP",12), + ARGUS("ARGUS",13), + EMCON("EMCON",14), + XNET("XNET",15), + CHAOS("CHAOS",16), + */UDP("UDP", 17), + /* MUX("MUX",18), + DCNMEAS("DCN-MEAS",19), + HMP("HMP",20), + PRM("PRM",21), + XNSIDP("XNS-IDP",22), + TRUNK1("TRUNK-1",23), + TRUNK2("TRUNK-2",24), + LEAF1("LEAF-1",25), + LEAF2("LEAF-2",26), + RDP("RDP",27), + IRTP("IRTP",28), + ISOTP4("ISO-TP4",29), + NETBLT("NETBLT",30), + MFENSP("MFE-NSP",31), + MERITINP("MERIT-INP",32), + DCCP("DCCP",33), + THREEPC("3PC",34), + IDPR("IDPR",35), + XTP("XTP",36), + DDP("DDP",37), + IDPRCMTP("IDPR-CMTP",38), + TPPLUSPLUS("TP++",39), + IL("IL",40), + IPV6("IPv6",41), + SDRP("SDRP",42), + IPV6Route("IPv6-Route",43), + IPV6Frag("IPv6-Frag",44), + IDRP("IDRP",45), + RSVP("RSVP",46), + GRE("GRE",47), + DSR("DSR",48), + BNA("BNA",49), + ESP("ESP",50), + AH("AH",51), + INLSP("I-NLSP",52), + SWIPE("SWIPE",53), + NARP("NARP",54), + MOBILE("MOBILE",55), + TLSP("TLSP",56), + SKIP("SKIP",57), + */IPV6ICMP("IPv6-ICMP", 58); + /* IPV6NoNxt("IPv6-NoNxt",59), + IPV6Opts("IPv6-Opts",60), + ANYHOST("ANY-HOST",61), + CFTP("CFTP",62), + ANYNETWORK("ANY-NETWORK",63), + SATEXPAK("SAT-EXPAK",64), + KRYPTOLAN("KRYPTOLAN",65), + RVD("RVD",66), + IPPC("IPPC",67), + ANYDISTFS("ANY-DIST-FS",68), + SATMON("SAT-MON",69), + VISA("VISA",70), + IPCV("IPCV",71), + CPNX("CPNX",72), + CPHB("CPHB",73), + WSN("WSN",74), + PVP("PVP",75), + BRSATMON("BR-SAT-MON",76), + SUNND("SUN-ND",77), + WBMON("WB-MON",78), + WBEXPAK("WB-EXPAK",79), + ISOIP("ISO-IP",80), + VMTP("VMTP",81), + SECUREVMTP("SECURE-VMTP",82), + VINES("VINES",83), + TTP("TTP",84), + IPTM("IPTM",84), + NSFNETIGP("NSFNET-IGP",85), + DGP("DGP",86), + TCF("TCF",87), + EIGRP("EIGRP",88), + OSPFIGP("OSPFIGP",89), + SPRITERPC("Sprite-RPC",90), + LARP("LARP",91), + MTP("MTP",92), + AX25("AX.25",93), + IPIP("IPIP",94), + MICP("MICP",95), + SCCSP("SCC-SP",96), + ETHERIP("ETHERIP",97), + ENCAP("ENCAP",98), + ANYENC("ANY-ENC",99), + GMTP("GMTP",100), + IFMP("IFMP",101), + PNNI("PNNI",102), + PIM("PIM",103), + ARIS("ARIS",104), + SCPS("SCPS",105), + QNX("QNX",106), + AN("A/N",107), + IPComp("IPComp",108), + SNP("SNP",109), + COMPAQPEER("Compaq-Peer",110), + IPXINIP("IPX-in-IP",111), + VRRP("VRRP",112), + PGM("PGM",113), + ANY0HOP("ANY-0-HOP",114), + L2TP("L2TP",115), + DDX("DDX",116), + IATP("IATP",117), + STP("STP",118), + SRP("SRP",119), + UTI("UTI",120), + SMP("SMP",121), + SM("SM",122), + PTP("PTP",123), + ISIS("ISIS",124), + FIRE("FIRE",125), + CRTP("CRTP",126), + CRUDP("CRUDP",127), + SSCOPMCE("SSCOPMCE",128), + IPLT("IPLT",129), + SPS("SPS",130), + PIPE("PIPE",131), + SCTP("SCTP",132), + FC("FC",133), + RSVPE2EIGNORE("RSVP-E2E-IGNORE",134), + MOBILITYHEADER("Mobility Header",135), + UDPLITE("UDPLite",136), + MPLSINIP("MPLS-in-IP",137), + MANET("MANET",138), + HIP("HIP",139), + SHIM6("Shim6",140), + WESP("WESP",141), + ROHC("ROHC",142); + */ + private static final String regexNumberString = "^[0-9]+$"; + private String protocolName; + private int protocolNumber; + + private IPProtocols(String name, int number) { + protocolName = name; + protocolNumber = number; + } + + public int intValue() { + return protocolNumber; + } + + public short shortValue() { + return ((Integer) protocolNumber).shortValue(); + } + + public byte byteValue() { + return ((Integer) protocolNumber).byteValue(); + } + + public String toString() { + return protocolName; + } + + public static String getProtocolName(int number) { + return getProtocolNameInternal(number); + } + + public static String getProtocolName(short number) { + return getProtocolNameInternal((int) number & 0xffff); + } + + public static String getProtocolName(byte number) { + return getProtocolNameInternal((int) number & 0xff); + } + + private static String getProtocolNameInternal(int number) { + for (IPProtocols proto : IPProtocols.values()) { + if (proto.protocolNumber == number) { + return proto.toString(); + } + } + return "0x" + Integer.toHexString(number); + } + + public static short getProtocolNumberShort(String name) { + if (name.matches(regexNumberString)) { + return Short.valueOf(name); + } + for (IPProtocols proto : IPProtocols.values()) { + if (proto.protocolName.equalsIgnoreCase(name)) { + return proto.shortValue(); + } + } + return 0; + } + + public static int getProtocolNumberInt(String name) { + if (name.matches(regexNumberString)) { + return Integer.valueOf(name); + } + for (IPProtocols proto : IPProtocols.values()) { + if (proto.protocolName.equalsIgnoreCase(name)) { + return proto.intValue(); + } + } + return 0; + } + + public static byte getProtocolNumberByte(String name) { + if (name.matches(regexNumberString)) { + return Integer.valueOf(name).byteValue(); + } + for (IPProtocols proto : IPProtocols.values()) { + if (proto.protocolName.equalsIgnoreCase(name)) { + return proto.byteValue(); + } + } + return 0; + } + + public static List getProtocolNameList() { + List protoList = new ArrayList(); + for (IPProtocols proto : IPProtocols.values()) { + protoList.add(proto.toString()); + } + return protoList; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NetUtils.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NetUtils.java new file mode 100644 index 0000000000..703d49a9c3 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NetUtils.java @@ -0,0 +1,341 @@ + +/* + * 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.controller.sal.utils; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility class containing the common utility functions needed + * for operating on networking data structures + * + * + * + */ +public abstract class NetUtils { + /** + * Constant holding the number of bits in a byte + */ + public static final int NumBitsInAByte = 8; + + /** + * Converts a 4 bytes array into an integer number + * + * @param ba the 4 bytes long byte array + * @return the integer number + */ + public static int byteArray4ToInt(byte[] ba) { + if (ba == null || ba.length != 4) + return 0; + return (int) ((0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 + | (0xff & ba[2]) << 8 | (0xff & ba[3])); + } + + /** + * Converts an integer number into a 4 bytes array + * + * @param i the integer number + * @return the byte array + */ + public static byte[] intToByteArray4(int i) { + return new byte[] { (byte) ((i >> 24) & 0xff), + (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff), + (byte) (i & 0xff) }; + } + + /** + * Converts an IP address passed as integer value into the + * respective InetAddress object + * + * @param address the IP address in integer form + * @return the IP address in InetAddress form + */ + public static InetAddress getInetAddress(int address) { + InetAddress ip = null; + try { + ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address)); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + return ip; + } + + /** + * Return the InetAddress Network Mask given the length of the prefix bit mask. + * The prefix bit mask indicates the contiguous leading bits that are NOT masked out. + * Example: A prefix bit mask length of 8 will give an InetAddress Network Mask of 255.0.0.0 + * + * @param prefixMaskLength integer representing the length of the prefix network mask + * @param isV6 boolean representing the IP version of the returned address + * @return + */ + public static InetAddress getInetNetworkMask(int prefixMaskLength, + boolean isV6) { + if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32) + || (isV6 && prefixMaskLength > 128)) { + return null; + } + byte v4Address[] = { 0, 0, 0, 0 }; + byte v6Address[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + byte address[] = (isV6) ? v6Address : v4Address; + int numBytes = prefixMaskLength / 8; + int numBits = prefixMaskLength % 8; + int i = 0; + for (; i < numBytes; i++) { + address[i] = (byte) 0xff; + } + if (numBits > 0) { + int rem = 0; + for (int j = 0; j < numBits; j++) { + rem |= 1 << (7 - j); + } + address[i] = (byte) rem; + } + + try { + return InetAddress.getByAddress(address); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Returns the number of contiguous bits belonging to the subnet, that have to be masked out + * Example: A prefix network byte mask of ff.ff.ff.00 will give a subnet mask length of 8, + * while ff.00.00.00 will return a subnet mask length of 24. + * If the passed prefixMask object is null, 0 is returned + * + * @param prefixMask the prefix mask as byte array + * @return the length of the prefix network mask + */ + public static int getSubnetMaskLength(byte[] prefixMask) { + int maskLength = 0; + if (prefixMask != null) { + // Create bit mask + int intMask = 0; + int numBytes = prefixMask.length; + for (int i = 0; i < numBytes; i++) { + intMask |= ((int) prefixMask[i] & 0xff) << (8 * (numBytes - 1 - i)); + } + + int bit = 1; + while (((intMask & bit) == 0) && (maskLength <= (numBytes * 8))) { + maskLength += 1; + bit = bit << 1; + } + } + return maskLength; + } + + /** + * Returns the number of contiguous bits belonging to the subnet, that have to be masked out + * Example: A prefix network byte mask of ff.ff.ff.00 will give a subnet mask length of 8, + * while ff.00.00.00 will return a subnet mask length of 24 + * If the passed prefixMask object is null, 0 is returned + * + * @param prefixMask the prefix mask as InetAddress + * @return the length of the prefix network mask + */ + public static int getSubnetMaskLength(InetAddress prefixMask) { + return (prefixMask == null) ? 0 : NetUtils + .getSubnetMaskLength(prefixMask.getAddress()); + } + + /** + * Given an IP address and a prefix network mask length, it returns + * the equivalent subnet prefix IP address + * Example: for ip = "172.28.30.254" and maskLen = 25 it will return "172.28.30.128" + * + * @param ip the IP address in InetAddress form + * @param maskLen the length of the prefix network mask + * @return the subnet prefix IP address in InetAddress form + */ + public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) { + int bytes = maskLen / 8; + int bits = maskLen % 8; + byte modifiedByte; + byte[] sn = ip.getAddress(); + if (bits > 0) { + modifiedByte = (byte) (sn[bytes] >> (8 - bits)); + sn[bytes] = (byte) (modifiedByte << (8 - bits)); + bytes++; + } + for (; bytes < sn.length; bytes++) { + sn[bytes] = (byte) (0); + } + try { + return InetAddress.getByAddress(sn); + } catch (UnknownHostException e) { + return null; + } + } + + /** + * Checks if the test address and mask conflicts with + * the filter address and mask + * + * For example: + * testAddress: 172.28.2.23 testMask: 255.255.255.0 + * filtAddress: 172.28.1.10 testMask: 255.255.255.0 + * conflict + * + * testAddress: 172.28.2.23 testMask: 255.255.255.0 + * filtAddress: 172.28.1.10 testMask: 255.255.0.0 + * do not conflict + * + * Null parameters are permitted + * + * @param testAddress + * @param filterAddress + * @param testMask + * @param filterMask + * @return + */ + public static boolean inetAddressConflict(InetAddress testAddress, + InetAddress filterAddress, InetAddress testMask, + InetAddress filterMask) { + // Sanity check + if ((testAddress == null) || (filterAddress == null)) { + return false; + } + + // Presence check + if (isAny(testAddress) || isAny(filterAddress)) { + return false; + } + + // Derive the masks length. A null mask means a full mask + int testMaskLen = (testMask != null) ? NetUtils + .getSubnetMaskLength(testMask.getAddress()) + : (testAddress instanceof Inet6Address) ? 128 : 32; + int filterMaskLen = (filterMask != null) ? NetUtils + .getSubnetMaskLength(filterMask.getAddress()) + : (filterAddress instanceof Inet6Address) ? 128 : 32; + + // Mask length check. Test mask has to be more generic than filter one + if (testMaskLen < filterMaskLen) { + return true; + } + + // Subnet Prefix on filter mask length must be the same + InetAddress prefix1 = getSubnetPrefix(testAddress, filterMaskLen); + InetAddress prefix2 = getSubnetPrefix(filterAddress, filterMaskLen); + return (!prefix1.equals(prefix2)); + } + + /** + * Returns true if the passed MAC address is all zero + * + * @param mac the byte array representing the MAC address + * @return true if all MAC bytes are zero + */ + public static boolean isZeroMAC(byte[] mac) { + for (short i = 0; i < 6; i++) { + if (mac[i] != 0) { + return false; + } + } + return true; + } + + /** + * Returns true if the passed InetAddress contains all zero + * + * @param ip the IP address to test + * @return true if the address is all zero + */ + public static boolean isAny(InetAddress ip) { + for (byte b : ip.getAddress()) { + if (b != 0) { + return false; + } + } + return true; + } + + public static boolean fieldsConflict(int field1, int field2) { + if ((field1 == 0) || (field2 == 0) || (field1 == field2)) { + return false; + } + return true; + } + + public static InetAddress parseInetAddress(String addressString) { + InetAddress address = null; + try { + address = InetAddress.getByName(addressString); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + return address; + } + + /** + * Checks if the passed IP v4 address in string form is valid + * The address may specify a mask at the end as "/MM" + * + * @param cidr the v4 address as A.B.C.D/MM + * @return + */ + public static boolean isIPv4AddressValid(String cidr) { + if (cidr == null) + return false; + + String values[] = cidr.split("/"); + Pattern ipv4Pattern = Pattern + .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])"); + Matcher mm = ipv4Pattern.matcher(values[0]); + if (!mm.matches()) { + return false; + } + if (values.length >= 2) { + int prefix = Integer.valueOf(values[1]); + if ((prefix < 0) || (prefix > 32)) { + return false; + } + } + return true; + } + + /** + * Checks if the passed IP v6 address in string form is valid + * The address may specify a mask at the end as "/MMM" + * + * @param cidr the v6 address as A::1/MMM + * @return + */ + public static boolean isIPv6AddressValid(String cidr) { + if (cidr == null) + return false; + + String values[] = cidr.split("/"); + try { + //when given an IP address, InetAddress.getByName validates the ip address + InetAddress addr = InetAddress.getByName(values[0]); + if (!(addr instanceof Inet6Address)) { + return false; + } + } catch (UnknownHostException ex) { + return false; + } + + if (values.length >= 2) { + int prefix = Integer.valueOf(values[1]); + if ((prefix < 0) || (prefix > 128)) { + return false; + } + } + return true; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeConnectorCreator.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeConnectorCreator.java new file mode 100644 index 0000000000..b04ce9a075 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeConnectorCreator.java @@ -0,0 +1,92 @@ + +/* + * 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.controller.sal.utils; + +import java.util.HashSet; +import java.util.Set; + +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Node.NodeIDType; +import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; + +/** + * The class provides helper functions to create a node connector + * + * + */ +public abstract class NodeConnectorCreator { + /** + * Generic NodeConnector creator + * The nodeConnector type is inferred from the node type + * + * @param portId + * @param node + * @return + */ + public static NodeConnector createNodeConnector(Object portId, Node node) { + if (node.getType().equals(NodeIDType.OPENFLOW)) { + try { + return new NodeConnector(NodeConnectorIDType.OPENFLOW, + (Short) portId, node); + } catch (ConstructionException e1) { + e1.printStackTrace(); + return null; + } + } + return null; + } + + /** + * NodeConnector creator where NodeConnector type can be specified + * Needed to create special internal node connectors (like software stack) + * + * @param nodeConnectorType + * @param portId + * @param node + * @return + */ + public static NodeConnector createNodeConnector( + String nodeConnectorType, Object portId, Node node) { + try { + return new NodeConnector(nodeConnectorType, portId, node); + } catch (ConstructionException e1) { + e1.printStackTrace(); + return null; + } + } + + public static NodeConnector createOFNodeConnector(Short portId, Node node) { + try { + return new NodeConnector(NodeConnectorIDType.OPENFLOW, portId, node); + } catch (ConstructionException e1) { + e1.printStackTrace(); + return null; + } + } + + public static Set createOFNodeConnectorSet( + Set portIds, Node n) { + try { + Set nodeConnectors = new HashSet(); + for (Short ofPortID : portIds) { + NodeConnector p = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, Short + .valueOf(ofPortID), n); + nodeConnectors.add(p); + } + return nodeConnectors; + } catch (ConstructionException e1) { + e1.printStackTrace(); + return null; + } + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeCreator.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeCreator.java new file mode 100644 index 0000000000..6b068fb4ad --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NodeCreator.java @@ -0,0 +1,31 @@ + +/* + * 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.controller.sal.utils; + +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.Node.NodeIDType; + +/** + * Utility class for creating a Node object + * + * + * + */ +public abstract class NodeCreator { + public static Node createOFNode(Long switchId) { + try { + return new Node(NodeIDType.OPENFLOW, switchId); + } catch (ConstructionException e1) { + e1.printStackTrace(); + return null; + } + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ObjectReader.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ObjectReader.java new file mode 100644 index 0000000000..1b2225c11c --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ObjectReader.java @@ -0,0 +1,68 @@ + +/* + * 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.controller.sal.utils; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.ObjectInputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Read object to read from file stream + * + * + * + */ +public class ObjectReader { + private static Logger logger = LoggerFactory.getLogger(ObjectReader.class); + private FileInputStream fis; + public ObjectInputStream ois; + + public ObjectReader() { + fis = null; + ois = null; + } + + public Object read(IObjectReader reader, String file) { + Object obj = null; + try { + fis = new FileInputStream(file); + ois = new ObjectInputStream(fis); + obj = reader.readObject(ois); + } catch (FileNotFoundException fnfex) { + //logger.info("Cannot find {} for reading", file); + } catch (IOException ioex) { + logger.error("Failed to read from {}", file); + } catch (ClassNotFoundException cnfex) { + logger.error("Failed to interpret content of {}", file); + } catch (Exception e) { + + } finally { + if (ois != null) { + try { + ois.close(); + } catch (IOException ioex) { + logger.error("Failed to close object input stream: {}", + file); + } + } + if (fis != null) { + try { + fis.close(); + } catch (IOException ioex) { + logger.error("Failed to close input file stream: {}", file); + } + } + } + return obj; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ObjectWriter.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ObjectWriter.java new file mode 100644 index 0000000000..730a9b0368 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ObjectWriter.java @@ -0,0 +1,66 @@ + +/* + * 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.controller.sal.utils; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Write object to write to file stream + * + */ +public class ObjectWriter { + private static Logger logger = LoggerFactory.getLogger(ObjectWriter.class); + private FileOutputStream fos; + private ObjectOutputStream oos; + + public ObjectWriter() { + fos = null; + oos = null; + } + + public Status write(Object obj, String file) { + try { + fos = new FileOutputStream(file); + oos = new ObjectOutputStream(fos); + oos.writeObject(obj); + } catch (FileNotFoundException fex) { + logger.error("Cannot create {} for writing", file); + return new Status(StatusCode.INTERNALERROR, "IO Error"); + } catch (IOException ioex) { + logger.error("Failed to write to {}", file); + return new Status(StatusCode.INTERNALERROR, "IO Error"); + } finally { + if (oos != null) { + try { + oos.close(); + } catch (IOException ioex) { + logger.error("Failed to close object output stream: {}", + file); + } + } + if (fos != null) { + try { + fos.close(); + } catch (IOException ioex) { + logger + .error("Failed to close output file stream: {}", + file); + } + } + } + return new Status(StatusCode.SUCCESS, null); + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ReadFromFile.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ReadFromFile.java new file mode 100644 index 0000000000..1d31eaa65b --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ReadFromFile.java @@ -0,0 +1,55 @@ + +/* + * 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.controller.sal.utils; + +import java.util.ArrayList; +import java.io.*; + +/** + * Convenience object for reading from file + * + * + * + */ +public class ReadFromFile { + private FileInputStream fileStream; + private DataInputStream dataInput; + private BufferedReader bufferedReader; + private String fileName; + private File filePointer; + + public ReadFromFile(String name) throws FileNotFoundException { + fileName = name; + fileStream = new FileInputStream(this.fileName); + filePointer = new File(fileName); //needed to allow file deletion + } + + public ArrayList readFile() throws IOException { + dataInput = new DataInputStream(this.fileStream); + bufferedReader = new BufferedReader(new InputStreamReader(dataInput)); + + ArrayList lineList = new ArrayList(); + String line; + while ((line = bufferedReader.readLine()) != null) { + lineList.add(line); + } + bufferedReader.close(); + dataInput.close(); + fileStream.close(); + return lineList; + } + + public boolean delete() { + if (filePointer == null) { + return true; + } + return filePointer.delete(); + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ServiceHelper.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ServiceHelper.java new file mode 100644 index 0000000000..0555860696 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/ServiceHelper.java @@ -0,0 +1,222 @@ + +/* + * 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 + */ + +/** + * @file ServiceHelper.java + * + * @brief The class helps to register and retrieve OSGi service registry + */ +package org.opendaylight.controller.sal.utils; + +import java.util.Hashtable; +import org.osgi.framework.ServiceRegistration; +import java.util.Dictionary; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The class helps to register and retrieve OSGi service registry + * + * + */ +public class ServiceHelper { + private static final Logger logger = LoggerFactory + .getLogger(ServiceHelper.class); + + /** + * Register a Service in the OSGi service registry + * + * @param clazz The target class + * @param containerName The container name + * @param instance of the object exporting the service, be careful + * the object must implement/extend clazz else the registration + * will fail unless a ServiceFactory is passed as parameter + * @param properties The properties to be attached to the service + * registration + * @return true if registration happened, false otherwise + */ + public static boolean registerService(Class clazz, String containerName, + Object instance, Dictionary properties) { + if (properties == null) { + properties = (Dictionary) new Hashtable(); + } + properties.put("containerName", containerName); + return registerGlobalService(clazz, instance, properties); + } + + /** + * Register a Global Service in the OSGi service registry + * + * @param clazz The target class + * @param instance of the object exporting the service, be careful + * the object must implement/extend clazz else the registration + * will fail unless a ServiceFactory is passed as parameter + * @param properties The properties to be attached to the service + * registration + * @return true if registration happened, false otherwise + */ + public static boolean registerGlobalService(Class clazz, + Object instance, Dictionary properties) { + try { + BundleContext bCtx = FrameworkUtil.getBundle(instance.getClass()) + .getBundleContext(); + if (bCtx == null) { + logger.error("Could not retrieve the BundleContext"); + return false; + } + + ServiceRegistration registration = bCtx.registerService(clazz + .getName(), instance, properties); + if (registration == null) { + logger.error("Failed to register {} for instance {}", clazz, + instance); + } + return true; + } catch (Exception e) { + logger.error("Exception "+e.getMessage() +" while registering the service "+instance.toString()); + } + return false; + } + + /** + * Retrieve instance of a class via OSGI registry, if there + * are many only the first is returned. + * + * @param clazz The target class + * @param containerName The container name + * @param bundle The caller + */ + public static Object getInstance(Class clazz, String containerName, + Object bundle) { + // Back-end convention: Container id in lower case. Let's enforce it here + return getInstance(clazz, containerName.toLowerCase(), bundle, null); + } + + /** + * Retrieve global instance of a class via OSGI registry, if + * there are many only the first is returned. + * + * @param clazz The target class + * @param bundle The caller + */ + public static Object getGlobalInstance(Class clazz, Object bundle) { + return getGlobalInstance(clazz, bundle, null); + } + + /** + * Retrieve instance of a class via OSGI registry, if there + * are many only the first is returned. On this version an LDAP + * type of filter is applied + * + * @param clazz The target class + * @param containerName The container name + * @param bundle The caller + * @param serviceFilter LDAP filter to be applied in the search + */ + public static Object getInstance(Class clazz, String containerName, + Object bundle, String serviceFilter) { + Object[] instances = getInstances(clazz, containerName, bundle, + serviceFilter); + if (instances != null) { + return instances[0]; + } + return null; + } + + /** + * Retrieve global instance of a class via OSGI registry, if + * there are many only the first is returned. On this version an LDAP + * type of filter is applied + * + * @param clazz The target class + * @param bundle The caller + * @param serviceFilter LDAP filter to be applied in the search + */ + public static Object getGlobalInstance(Class clazz, Object bundle, + String serviceFilter) { + Object[] instances = getGlobalInstances(clazz, bundle, serviceFilter); + if (instances != null) { + return instances[0]; + } + return null; + } + + /** + * Retrieve all the Instances of a Service, optionally + * filtered via serviceFilter if non-null else all the results are + * returned if null + * + * @param clazz The target class + * @param containerName The container name + * @param bundle The caller + * @param serviceFilter LDAP filter to be applied in the search + */ + public static Object[] getInstances(Class clazz, String containerName, + Object bundle, String serviceFilter) { + Object instances[] = null; + try { + BundleContext bCtx = FrameworkUtil.getBundle(bundle.getClass()) + .getBundleContext(); + + ServiceReference[] services = null; + if (serviceFilter != null) { + services = bCtx.getServiceReferences(clazz.getName(), + "(&(containerName=" + containerName + ")" + + serviceFilter + ")"); + } else { + services = bCtx.getServiceReferences(clazz.getName(), + "(containerName=" + containerName + ")"); + } + + if (services != null) { + instances = new Object[services.length]; + for (int i = 0; i < services.length; i++) { + instances[i] = bCtx.getService(services[i]); + } + } + } catch (Exception e) { + logger.error("Instance reference is NULL"); + } + return instances; + } + + /** + * Retrieve all the Instances of a Service, optionally + * filtered via serviceFilter if non-null else all the results are + * returned if null + * + * @param clazz The target class + * @param bundle The caller + * @param serviceFilter LDAP filter to be applied in the search + */ + public static Object[] getGlobalInstances(Class clazz, Object bundle, + String serviceFilter) { + Object instances[] = null; + try { + BundleContext bCtx = FrameworkUtil.getBundle(bundle.getClass()) + .getBundleContext(); + + ServiceReference[] services = bCtx.getServiceReferences(clazz + .getName(), serviceFilter); + + if (services != null) { + instances = new Object[services.length]; + for (int i = 0; i < services.length; i++) { + instances[i] = bCtx.getService(services[i]); + } + } + } catch (Exception e) { + logger.error("Instance reference is NULL"); + } + return instances; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java new file mode 100644 index 0000000000..9bd98ac1ab --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/Status.java @@ -0,0 +1,75 @@ +package org.opendaylight.controller.sal.utils; + +/** + * Represents the return object of the osgi service interfaces function calls. + * It contains a code {@code StatusCode} representing the result of the call + * and a string which describes a failure reason (if any) in human readable form. + */ +public class Status { + StatusCode code; + String description; + + /** + * Generates an instance of the Status class. + * + * @param errorCode The status code. If passed as null, code will be + * stored as {@code StatusCode.UNDEFINED} + * @param description The human readable description of the status. If passed + * as null, description will be inferred by the code + */ + public Status(StatusCode errorCode, String description) { + this.code = (errorCode != null)? errorCode : StatusCode.UNDEFINED; + this.description = (description != null)? description : this.code.toString(); + } + + /** + * Returns the status code + * @return the {@code StatusCode} representing the status code + */ + public StatusCode getCode() { + return code; + } + + /** + * Returns a human readable description of the failure if any + * @return a string representing the reason of failure + */ + public String getDescription() { + return description; + } + + /** + * Tells whether the status is successful + * @return true if the Status code is {@code StatusCode.SUCCESS} + */ + public boolean isSuccess() { + return code == StatusCode.SUCCESS; + } + + @Override + public String toString() { + return code + ": " + description; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((code == null) ? 0 : code.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Status other = (Status) obj; + if (code != other.code) + return false; + return true; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/StatusCode.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/StatusCode.java new file mode 100644 index 0000000000..aca7919d01 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/StatusCode.java @@ -0,0 +1,40 @@ +package org.opendaylight.controller.sal.utils; + +/** + * The enum which describes the generic error conditions. + * Each enum value is associated with a minimal description string. + * + */ +public enum StatusCode { + SUCCESS("Success"), + + BADREQUEST("Bad Request"), + UNAUTHORIZED("UnAuthorized"), + FORBIDDEN("Forbidden"), + NOTFOUND("Not Found"), + NOTALLOWED("Method Not Allowed"), + NOTACCEPTABLE("Request Not Acceptable"), + TIMEOUT("Request Timeout"), + CONFLICT("Resource Conflict"), + GONE("Resource Gone"), + UNSUPPORTED("Unsupported"), + + INTERNALERROR("Internal Error"), + NOTIMPLEMENTED("Not Implemented"), + NOSERVICE("Service Not Available"), + + UNDEFINED("Undefined Error"); + + private String description; + private StatusCode(String description) { + this.description = description; + } + + /** + * Prints the description associated to the code value + */ + public String toString() { + return description; + } + +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/TierHelper.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/TierHelper.java new file mode 100644 index 0000000000..f8b61b0dc4 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/TierHelper.java @@ -0,0 +1,51 @@ + +/* + * 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.controller.sal.utils; + +import java.util.ArrayList; +import java.util.List; + +public final class TierHelper { + private static TierHelper tierHelper; + public static final int unknownTierNumber = 0; + private List tierNames; + + static { + tierHelper = new TierHelper(); + } + + private TierHelper() { + tierNames = new ArrayList(); + tierNames.add("Unknown"); + tierNames.add("Access"); + tierNames.add("Distribution"); + tierNames.add("Core"); + } + + public static void setTierName(int tier, String name) { + if (tier > tierHelper.tierNames.size() - 1) { + for (int i = tierHelper.tierNames.size() - 1; i < tier; i++) { + tierHelper.tierNames.add("Unknown"); + } + } + tierHelper.tierNames.set(tier, name); + } + + public static String getTierName(int tier) { + if ((tier < 0) || (tier > tierHelper.tierNames.size() - 1)) { + return "Unknown"; + } + return tierHelper.tierNames.get(tier); + } + + public static List getTiers() { + return tierHelper.tierNames; + } +} diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/WriteToFile.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/WriteToFile.java new file mode 100644 index 0000000000..0345b90cd7 --- /dev/null +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/WriteToFile.java @@ -0,0 +1,53 @@ + +/* + * 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.controller.sal.utils; + +import java.io.*; +import java.util.ArrayList; + +/** + * Convenience object to write a file + * + * + * + */ +public class WriteToFile { + private FileWriter fstream; + private BufferedWriter bufferOut; + private String fileName; + + public WriteToFile(String name) throws IOException { + fileName = name; + fstream = new FileWriter(fileName); + bufferOut = new BufferedWriter(fstream); + } + + public void save(ArrayList entryList) throws IOException { + for (String entry : entryList) { + bufferOut.write(entry); + bufferOut.append('\n'); + } + try { + this.bufferOut.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public boolean close() { + try { + bufferOut.close(); + fstream.close(); + } catch (IOException e) { + return false; + } + return true; + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/action/ActionTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/action/ActionTest.java new file mode 100644 index 0000000000..cf0f022980 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/action/ActionTest.java @@ -0,0 +1,237 @@ + +/* + * 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.controller.sal.action; + +import org.opendaylight.controller.sal.core.ConstructionException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.junit.Assert; +import org.opendaylight.controller.sal.action.Action; +import org.opendaylight.controller.sal.action.Controller; +import org.opendaylight.controller.sal.action.Output; +import org.opendaylight.controller.sal.action.PopVlan; +import org.opendaylight.controller.sal.action.PushVlan; +import org.opendaylight.controller.sal.action.SetDlSrc; +import org.opendaylight.controller.sal.action.SetNwDst; +import org.opendaylight.controller.sal.action.SetNwSrc; +import org.opendaylight.controller.sal.action.SetNwTos; +import org.opendaylight.controller.sal.action.SetTpDst; +import org.opendaylight.controller.sal.action.SetTpSrc; +import org.opendaylight.controller.sal.action.SetVlanCfi; +import org.opendaylight.controller.sal.action.SetVlanId; +import org.opendaylight.controller.sal.action.SetVlanPcp; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.NodeConnectorCreator; + +public class ActionTest { + @Test + public void tesActionCreationValidation() { + Action action = new PopVlan(); + Assert.assertTrue(action.isValid()); + + byte mac[] = { (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0x11, + (byte) 0x22, (byte) 0x33 }; + + action = new SetDlSrc(mac); + Assert.assertTrue(action.isValid()); + + action = new SetDlSrc(mac); + Assert.assertTrue(action.isValid()); + } + + @Test + public void testSetVlanActionCreation() { + Action action = null; + + action = new SetVlanId(2); + Assert.assertTrue(action.isValid()); + + action = new SetVlanId(4095); + Assert.assertTrue(action.isValid()); + + action = new SetVlanId(0); + Assert.assertFalse(action.isValid()); + + action = new SetVlanId(1); + Assert.assertFalse(action.isValid()); + + action = new SetVlanId(4096); + Assert.assertFalse(action.isValid()); + } + + @Test + public void testPushVlanActionCreation() { + Action action = null; + + action = new PushVlan(EtherTypes.QINQ, 0x4, 0x1, 2000); + Assert.assertTrue(action.isValid()); + + action = new PushVlan(EtherTypes.QINQ.intValue(), 0x4, 0x1, 2000); + Assert.assertTrue(action.isValid()); + + action = new PushVlan(EtherTypes.OLDQINQ, 0x4, 2, 2000); + Assert.assertFalse(action.isValid()); + + action = new PushVlan(EtherTypes.VLANTAGGED, 0x4, 0, 2000); + Assert.assertTrue(action.isValid()); + + action = new PushVlan(EtherTypes.QINQ.intValue(), 0x4, 0x1, 5000); + Assert.assertFalse(action.isValid()); + + action = new PushVlan(EtherTypes.LLDP, 0x4, 0x1, 2000); + Assert.assertFalse(action.isValid()); + + action = new PushVlan(EtherTypes.PVSTP, 0x4, 2, 2000); + Assert.assertFalse(action.isValid()); + + action = new PushVlan(EtherTypes.QINQ, 0x4, -1, 2000); + Assert.assertFalse(action.isValid()); + } + + @Test + public void testSetVlanPcpActionCreation() { + Action action = null; + + action = new SetVlanPcp(0x4); + Assert.assertTrue(action.isValid()); + + action = new SetVlanPcp(0x8); + Assert.assertFalse(action.isValid()); + + action = new SetVlanPcp(-1); + Assert.assertFalse(action.isValid()); + } + + @Test + public void testSetVlanCfiActionCreation() { + Action action = null; + + action = new SetVlanCfi(0x0); + Assert.assertTrue(action.isValid()); + + action = new SetVlanCfi(0x1); + Assert.assertTrue(action.isValid()); + + action = new SetVlanCfi(0x2); + Assert.assertFalse(action.isValid()); + + action = new SetVlanCfi(-1); + Assert.assertFalse(action.isValid()); + } + + @Test + public void testNetworkSetActionCreation() { + Action action = null; + + InetAddress ip = null; + try { + ip = InetAddress.getByName("171.71.9.52"); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + + action = new SetNwSrc(ip); + Assert.assertTrue(action.isValid()); + + action = new SetNwDst(ip); + Assert.assertTrue(action.isValid()); + + try { + ip = InetAddress.getByName("2001:420:281:1003:f2de:f1ff:fe71:728d"); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + action = new SetNwSrc(ip); + Assert.assertTrue(action.isValid()); + + action = new SetNwDst(ip); + Assert.assertTrue(action.isValid()); + + action = new SetNwTos(0xf); + Assert.assertTrue(action.isValid()); + + action = new SetNwTos(0xff); + Assert.assertTrue(action.isValid()); + + action = new SetNwTos(0xff1); + Assert.assertFalse(action.isValid()); + + action = new SetNwTos(-1); + Assert.assertFalse(action.isValid()); + } + + @Test + public void testTransportSetActionCreation() { + Action action = null; + + action = new SetTpSrc(50000); + Assert.assertTrue(action.isValid()); + + action = new SetTpDst(65535); + Assert.assertTrue(action.isValid()); + + action = new SetTpDst(0); + Assert.assertTrue(action.isValid()); + + action = new SetTpSrc(-1); + Assert.assertFalse(action.isValid()); + + action = new SetTpDst(-1); + Assert.assertFalse(action.isValid()); + + action = new SetTpSrc(65536); + Assert.assertFalse(action.isValid()); + + action = new SetTpDst(65536); + Assert.assertFalse(action.isValid()); + } + + @Test + public void testActionList() { + List actions = new ArrayList(); + short portId = (short) 9; + Node node = null; + try { + node = new Node(Node.NodeIDType.OPENFLOW, new Long(0x55667788L)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + NodeConnector nc = NodeConnectorCreator.createNodeConnector(portId, + node); + byte mac[] = { (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0x11, + (byte) 0x22, (byte) 0x33 }; + InetAddress ip = null; + try { + ip = InetAddress.getByName("1.1.1.1"); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + + actions.add(new SetDlSrc(mac)); + actions.add(new SetNwSrc(ip)); + actions.add(new Output(nc)); + Assert.assertTrue(actions.size() == 3); + Assert.assertTrue(actions.get(0).isValid()); + + Action probe = new Output(nc); + Assert.assertTrue(actions.contains(probe)); + Assert.assertFalse(actions.contains(new Output(NodeConnectorCreator + .createNodeConnector((short) 5, node)))); + Assert.assertFalse(actions.contains(new Controller())); + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/authorization/AuthorizationTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/authorization/AuthorizationTest.java new file mode 100644 index 0000000000..518e9c607c --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/authorization/AuthorizationTest.java @@ -0,0 +1,67 @@ + +/* + * 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.controller.sal.authorization; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.junit.Assert; +import org.junit.Test; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.utils.NodeCreator; + + public class AuthorizationTest { + + @Test + public void testResources () { + Privilege p = Privilege.WRITE; + ResourceGroup resourceGroup = new ResourceGroup("NodeGroup", p); + Map> resourceMap = new HashMap>(); + ArrayList resourceList = new ArrayList(); + + for (int i = 0; i < 5; i++) { + Node node = NodeCreator.createOFNode((long)i); + Resource resource = new Resource (node, p); + resourceList.add(resource); + } + + resourceMap.put(resourceGroup, resourceList); + + ArrayList retrievedResourceList = resourceMap.get(resourceGroup); + for (Entry> entry : resourceMap.entrySet()) { + ResourceGroup rGroup = entry.getKey(); + Assert.assertTrue(rGroup.getGroupName().equals(resourceGroup.getGroupName())); + for (int i = 0; i < 5; i++) { + Resource resource = retrievedResourceList.get(i); + Assert.assertTrue(resource.getPrivilege().equals(Privilege.WRITE)); + Assert.assertTrue(((Long)((Node)resource.getResource()).getID()).equals((long)i)); + } + } + } + + @Test + public void testAppRoleLevel() { + AppRoleLevel appRoleLevel = AppRoleLevel.APPOPERATOR; + Assert.assertTrue(appRoleLevel.toString().equals("Network-Operator")); + Assert.assertTrue(appRoleLevel.toNumber() == 2); + Assert.assertTrue(appRoleLevel.toStringPretty().equals("Application Operator")); + } + + @Test + public void testUserLevel() { + UserLevel userLevel = UserLevel.SYSTEMADMIN; + Assert.assertTrue(userLevel.toString().equals("System-Admin")); + Assert.assertTrue(userLevel.toNumber() == 0); + Assert.assertTrue(userLevel.toStringPretty().equals("System Administrator")); + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/EdgeTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/EdgeTest.java new file mode 100644 index 0000000000..f3a9a6b160 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/EdgeTest.java @@ -0,0 +1,190 @@ + +/* + * 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 + */ + +/** + * @file EdgeTest.java + * + * @brief Unit Tests for Edge element + * + * Unit Tests for Edge element + */ +package org.opendaylight.controller.sal.core; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Edge; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; + +public class EdgeTest { + @Test + public void testEdgeEquals() { + try { + Node n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c0 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x4), n0); + + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n1); + + Node n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x4), n2); + + Node n3 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c3 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n3); + + Edge e0 = new Edge(c0, c1); + Edge e1 = new Edge(c2, c3); + // e0 must be equal to e1 to pass the test + Assert.assertTrue(e0.equals(e1)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + } + + @Test + public void testEdgeDifferents() { + Node n0, n1, n2, n3; + NodeConnector c0, c1, c2, c3; + Edge e0, e1; + try { + // Difference in the tail node + n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c0 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n0); + + n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + c1 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x1), n1); + + e0 = new Edge(c0, c1); + + n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c2 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n2); + + n3 = new Node(Node.NodeIDType.OPENFLOW, new Long(111L)); + c3 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x1), n3); + + e0 = new Edge(c0, c1); + e1 = new Edge(c2, c3); + // e0 must be different from e1 to pass the test + Assert.assertTrue(!e0.equals(e1)); + + // Difference in the head node + n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c0 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n0); + + n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + c1 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x1), n1); + + e0 = new Edge(c0, c1); + + n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(41L)); + c2 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n2); + + n3 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + c3 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x1), n3); + + e0 = new Edge(c0, c1); + e1 = new Edge(c2, c3); + // e0 must be different from e1 to pass the test + Assert.assertTrue(!e0.equals(e1)); + + // Difference in the head nodeconnetor + n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c0 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n0); + + n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + c1 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x1), n1); + + e0 = new Edge(c0, c1); + + n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c2 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x5), n2); + + n3 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + c3 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x1), n3); + + e0 = new Edge(c0, c1); + e1 = new Edge(c2, c3); + // e0 must be different from e1 to pass the test + Assert.assertTrue(!e0.equals(e1)); + + // Difference in the tail nodeconnetor + n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c0 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n0); + + n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + c1 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x1), n1); + + e0 = new Edge(c0, c1); + + n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c2 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n2); + + n3 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + c3 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x2), n3); + + e0 = new Edge(c0, c1); + e1 = new Edge(c2, c3); + // e0 must be different from e1 to pass the test + Assert.assertTrue(!e0.equals(e1)); + + // Difference in the both nodeconnetor/node + n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c0 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n0); + + n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + c1 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x1), n1); + + e0 = new Edge(c0, c1); + + n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + c2 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x4), n2); + + n3 = new Node(Node.NodeIDType.OPENFLOW, new Long(111L)); + c3 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, + new Short((short) 0x2), n3); + + e0 = new Edge(c0, c1); + e1 = new Edge(c2, c3); + // e0 must be different from e1 to pass the test + Assert.assertTrue(!e0.equals(e1)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/NodeConnectorTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/NodeConnectorTest.java new file mode 100644 index 0000000000..f7e8f4515d --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/NodeConnectorTest.java @@ -0,0 +1,1280 @@ + +/* + * 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 + */ + +/** + * @file NodeConnectorTest.java + * + * @brief Unit Tests for NodeConnector element + * + * Unit Tests for NodeConnector element + */ +package org.opendaylight.controller.sal.core; + +import java.util.UUID; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; + +public class NodeConnectorTest { + @Test + public void testNodeConnectorOpenFlowOfWrongType() { + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector of1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new String( + "0xDEADBEEFCAFE0001L"), n1); + + // If we reach this point the exception was not raised + // which should have been the case + Assert.assertTrue(false); + } catch (ConstructionException e) { + // If we reach this point the exception has been raised + // and so test passed + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(true); + } + } + + @Test + public void testNodeConnectorONEPKOfWrongType() { + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector onepk1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new Long( + 0xDEADBEEFCAFE0001L), n1); + + // If we reach this point the exception was not raised + // which should have been the case + Assert.assertTrue(false); + } catch (ConstructionException e) { + // If we reach this point the exception has been raised + // and so test passed + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(true); + } + } + + @Test + public void testNodeConnectorPCEPOfWrongType() { + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector pcep1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Long( + 0xDEADBEEFCAFE0001L), n1); + + // If we reach this point the exception was not raised + // which should have been the case + Assert.assertTrue(false); + } catch (ConstructionException e) { + // If we reach this point the exception has been raised + // and so test passed + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(true); + } + } + + @Test + public void testNodeConnectorOpenFlowOfCorrectType() { + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector of1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xCAFE), n1); + + // If we reach this point the exception has not been + // raised so we passed the test + System.out.println("Got node:" + of1); + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testNodeConnectorONEPKOfCorrectType() { + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector onepk1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + + // If we reach this point the exception has not been + // raised so we passed the test + System.out.println("Got node:" + onepk1); + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testNodeConnectorPCEPOfCorrectType() { + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector pcep1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer( + 0xDEADBEEF), n1); + + // If we reach this point the exception has not been + // raised so we passed the test + System.out.println("Got node:" + pcep1); + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoOpenFlowNodeConnectorEquals() { + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector of1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xCAFE), n1); + NodeConnector of2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xCAFE), n1); + + Assert.assertTrue(of1.equals(of2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoONEPKNodeConnectorEquals() { + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector onepk1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + NodeConnector onepk2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + + Assert.assertTrue(onepk1.equals(onepk2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoPCEPNodeConnectorEquals() { + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector pcep1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer( + 0xDEADBEEF), n1); + NodeConnector pcep2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer( + 0xDEADBEEF), n1); + + Assert.assertTrue(pcep1.equals(pcep2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoOpenFlowNodeConnectorDifferents() { + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector of1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xCAFE), n1); + NodeConnector of2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xBEEF), n1); + + Assert.assertTrue(!of1.equals(of2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoONEPKNodeConnectorDifferents() { + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector onepk1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + NodeConnector onepk2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/2"), n1); + + Assert.assertTrue(!onepk1.equals(onepk2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoPCEPNodeConnectorDifferents() { + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector pcep1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer( + 0xDEADBEEF), n1); + NodeConnector pcep2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer( + 0xCAFECAFE), n1); + + Assert.assertTrue(!pcep1.equals(pcep2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoOpenFlowNodeConnectorDifferentsNodes() { + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + Node n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(111L)); + NodeConnector of1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xCAFE), n1); + NodeConnector of2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xCAFE), n2); + + Assert.assertTrue(!of1.equals(of2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoONEPKNodeConnectorDifferentsNodes() { + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + Node n2 = new Node(Node.NodeIDType.ONEPK, new String("Router2")); + NodeConnector onepk1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + NodeConnector onepk2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n2); + + Assert.assertTrue(!onepk1.equals(onepk2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoPCEPNodeConnectorDifferentsNodes() { + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + Node n2 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 1L)); + NodeConnector pcep1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer( + 0xDEADBEEF), n1); + NodeConnector pcep2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer( + 0xDEADBEEF), n2); + + Assert.assertTrue(!pcep1.equals(pcep2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testIncompatibleNodes() { + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2PCEP, new Short( + (short) 0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2PCEP, new String( + "towardPCEP1"), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardPCEP1"), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer(0), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP2ONEPK, + new Integer(0), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP2OPENFLOW, + new Integer(0), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2PCEP, new Short( + (short) 0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2PCEP, new String( + "towardPCEP1"), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardPCEP1"), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer(0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP2ONEPK, + new Integer(0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP2OPENFLOW, + new Integer(0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2PCEP, new Short( + (short) 0), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0), n1); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2PCEP, new String( + "towardPCEP1"), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardPCEP1"), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer(0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP2ONEPK, + new Integer(0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP2OPENFLOW, + new Integer(0), n1); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + } + + @Test + public void testConversionToStringAndBack() { + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID( + 0xDEADBEEFCAFE0001L, 0xDEADBEEFCAFE0002L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP2ONEPK, new Integer( + 0xDEADBEEF), n1); + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID( + 0xDEADBEEFCAFE0001L, 0xDEADBEEFCAFE0002L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP2OPENFLOW, + new Integer(0x10), n1); + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.PCEP, new UUID( + 0xDEADBEEFCAFE0001L, 0xDEADBEEFCAFE0002L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.PCEP, new Integer(0x10), + n1); + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2PCEP, new String( + "towardPCEP1"), n1); + + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardOPENFLOW1"), n1); + + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n1); + + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long( + 0xDEADBEEFCAFE0001L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xCAFE), n1); + + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(0x100L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2PCEP, new Short( + (short) 0x10), n1); + + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(0x100L)); + NodeConnector nc1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0x11), n1); + + String nc1Str = nc1.toString(); + System.out.println("NodeConnector String = " + nc1Str); + NodeConnector nc1FromStr = NodeConnector.fromString(nc1Str); + + // Make sure we got a nodeconnector + Assert.assertTrue(nc1FromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc1.equals(nc1FromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + } + + @Test + public void testNodeConnectorSpecialType() { + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.CONTROLLER, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.ALL, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.SWSTACK, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.HWPATH, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.CONTROLLER, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.ALL, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.SWSTACK, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.HWPATH, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.CONTROLLER, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.ALL, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.SWSTACK, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.HWPATH, + NodeConnector.SPECIALNODECONNECTORID, n); + System.out.println("Special NC = " + specialNc); + // We expect to reach this point succesfully + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + } + + @Test + public void testToStringConversionForOpenFlow() { + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x2AB), n); + + NodeConnector ofFromStr = null; + + ofFromStr = NodeConnector.fromStringNoNode("0x2ab", n); + + // Make sure we got a nodeconnector + Assert.assertTrue(ofFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc.equals(ofFromStr)); + + ofFromStr = NodeConnector.fromStringNoNode("0x2AB", n); + + // Make sure we got a nodeconnector + Assert.assertTrue(ofFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc.equals(ofFromStr)); + + ofFromStr = NodeConnector.fromStringNoNode("683", n); + + // Make sure we got a nodeconnector + Assert.assertTrue(ofFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc.equals(ofFromStr)); + } catch (Exception e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector nc = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0xcafe), n); + + NodeConnector ofFromStr = null; + + ofFromStr = NodeConnector.fromStringNoNode("-13570", n); + + // Make sure we got a nodeconnector + Assert.assertTrue(ofFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(nc.equals(ofFromStr)); + } catch (Exception e) { + // If this expection is raised the test is failing + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(false); + } + } + + @Test + public void testConversionToStringAndBackSpecialPorts() { + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.CONTROLLER, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.ALL, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.HWPATH, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.SWSTACK, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.CONTROLLER, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.ALL, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.HWPATH, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.SWSTACK, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.CONTROLLER, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.ALL, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.HWPATH, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + + try { + Node n = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector specialNc = new NodeConnector( + NodeConnector.NodeConnectorIDType.SWSTACK, + NodeConnector.SPECIALNODECONNECTORID, n); + + String specialNcStr = specialNc.toString(); + System.out.println("NodeConnector String obtained= " + specialNc); + NodeConnector specialNcFromStr = NodeConnector + .fromString(specialNcStr); + + // Make sure we got a nodeconnector + Assert.assertTrue(specialNcFromStr != null); + + // Now the converted nodeconnector need to be the same of the + // original one + Assert.assertTrue(specialNc.equals(specialNcFromStr)); + } catch (ConstructionException e) { + // Fail if exception raised + Assert.assertTrue(false); + } + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/NodeTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/NodeTest.java new file mode 100644 index 0000000000..c081e10645 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/NodeTest.java @@ -0,0 +1,427 @@ + +/* + * 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 + */ + +/** + * @file NodeTest.java + * + * @brief Unit Tests for Node element + * + * Unit Tests for Node element + */ +package org.opendaylight.controller.sal.core; + +import java.util.UUID; +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; + +public class NodeTest { + @Test + public void testNodeOpenFlowOfWrongType() { + try { + Node of1 = new Node(Node.NodeIDType.OPENFLOW, new String( + "0xDEADBEEFCAFE0001L")); + + // If we reach this point the exception was not raised + // which should have been the case + Assert.assertTrue(false); + } catch (ConstructionException e) { + // If we reach this point the exception has been raised + // and so test passed + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(true); + } + } + + @Test + public void testNodeONEPKOfWrongType() { + try { + Node onepk1 = new Node(Node.NodeIDType.ONEPK, new Long( + 0xDEADBEEFCAFE0001L)); + + // If we reach this point the exception was not raised + // which should have been the case + Assert.assertTrue(false); + } catch (ConstructionException e) { + // If we reach this point the exception has been raised + // and so test passed + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(true); + } + } + + @Test + public void testNodePCEPOfWrongType() { + try { + Node pcep1 = new Node(Node.NodeIDType.PCEP, new Long( + 0xDEADBEEFCAFE0001L)); + + // If we reach this point the exception was not raised + // which should have been the case + Assert.assertTrue(false); + } catch (ConstructionException e) { + // If we reach this point the exception has been raised + // and so test passed + System.out.println("Got exception as expected!:" + e); + Assert.assertTrue(true); + } + } + + @Test + public void testNodeOpenFlowOfCorrectType() { + try { + Node of1 = new Node(Node.NodeIDType.OPENFLOW, new Long( + 0xDEADBEEFCAFE0001L)); + + // If we reach this point the exception has not been + // raised so we passed the test + System.out.println("Got node:" + of1); + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testNodeONEPKOfCorrectType() { + try { + Node onepk1 = new Node(Node.NodeIDType.ONEPK, new String( + "0xDEADBEEFCAFE0001L")); + + // If we reach this point the exception has not been + // raised so we passed the test + System.out.println("Got node:" + onepk1); + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testNodePCEPOfCorrectType() { + try { + Node pcep1 = new Node(Node.NodeIDType.PCEP, new UUID(0L, 0L)); + + // If we reach this point the exception has not been + // raised so we passed the test + System.out.println("Got node:" + pcep1); + Assert.assertTrue(true); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoOpenFlowNodeEquals() { + try { + Node of1 = new Node(Node.NodeIDType.OPENFLOW, new Long( + 0xDEADBEEFCAFE0001L)); + Node of2 = new Node(Node.NodeIDType.OPENFLOW, new Long( + 0xDEADBEEFCAFE0001L)); + + Assert.assertTrue(of1.equals(of2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoONEPKNodeEquals() { + try { + Node onepk1 = new Node(Node.NodeIDType.ONEPK, new String( + "0xDEADBEEFCAFE0001L")); + Node onepk2 = new Node(Node.NodeIDType.ONEPK, new String( + "0xDEADBEEFCAFE0001L")); + + Assert.assertTrue(onepk1.equals(onepk2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoPCEPNodeEquals() { + try { + Node pcep1 = new Node(Node.NodeIDType.PCEP, new UUID( + 0xDEADBEEFCAFE0001L, 0L)); + Node pcep2 = new Node(Node.NodeIDType.PCEP, new UUID( + 0xDEADBEEFCAFE0001L, 0L)); + + Assert.assertTrue(pcep1.equals(pcep2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoOpenFlowNodeDifferents() { + try { + Node of1 = new Node(Node.NodeIDType.OPENFLOW, new Long( + 0xDEADBEEFCAFE0001L)); + Node of2 = new Node(Node.NodeIDType.OPENFLOW, new Long( + 0xDEADBEEFCAFE0002L)); + + Assert.assertTrue(!of1.equals(of2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoONEPKNodeDifferents() { + try { + Node onepk1 = new Node(Node.NodeIDType.ONEPK, new String( + "0xDEADBEEFCAFE0001L")); + Node onepk2 = new Node(Node.NodeIDType.ONEPK, new String( + "0xDEADBEEFCAFE0002L")); + + Assert.assertTrue(!onepk1.equals(onepk2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testTwoPCEPNodeDifferents() { + try { + Node pcep1 = new Node(Node.NodeIDType.PCEP, new UUID( + 0xDEADBEEFCAFE0001L, 0L)); + Node pcep2 = new Node(Node.NodeIDType.PCEP, new UUID( + 0xDEADBEEFCAFE0001L, 1L)); + + Assert.assertTrue(!pcep1.equals(pcep2)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testToStringConversionAndBack() { + // Test PCEP + try { + Node pcep = new Node(Node.NodeIDType.PCEP, new UUID( + 0xDEADBEEFCAFE0001L, 0L)); + + String pcepToStr = pcep.toString(); + System.out.println("Got String from PCEP=(" + pcepToStr + ")"); + + Node pcepFromStr = Node.fromString(pcepToStr); + + // Make sure we got a node + Assert.assertTrue(pcepFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(pcep.equals(pcepFromStr)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + + // Test ONEPK + try { + Node onepk = new Node(Node.NodeIDType.ONEPK, new String( + "0xDEADBEEFCAFE0001L")); + + String onepkToStr = onepk.toString(); + System.out.println("Got String from ONEPK=(" + onepkToStr + ")"); + + Node onepkFromStr = Node.fromString(onepkToStr); + + // Make sure we got a node + Assert.assertTrue(onepkFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(onepk.equals(onepkFromStr)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + + // Test OPENFLOW short string + try { + Node of = new Node(Node.NodeIDType.OPENFLOW, new Long(0x10L)); + + String ofToStr = of.toString(); + System.out.println("Got String from OPENFLOW=(" + ofToStr + ")"); + + Node ofFromStr = Node.fromString(ofToStr); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + + // Test OPENFLOW longer string + try { + Node of = new Node(Node.NodeIDType.OPENFLOW, new Long( + 0xDEADBEEFCAFE0001L)); + + String ofToStr = of.toString(); + System.out.println("Got String from OPENFLOW=(" + ofToStr + ")"); + + Node ofFromStr = Node.fromString(ofToStr); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testToStringConversionForOpenFlow() { + // Test OPENFLOW longer string + try { + Node of = new Node(Node.NodeIDType.OPENFLOW, new Long( + 0xDEADBEEFCAFE0001L)); + Node ofFromStr = null; + + // Decimal value for deadbeefcafe0001 + ofFromStr = Node.fromString("-2401053089206501375"); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + + ofFromStr = Node.fromString("deadbeefcafe0001"); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + + ofFromStr = Node.fromString("DEADBEEFCAFE0001"); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + + ofFromStr = Node.fromString("0xdeadbeefcafe0001"); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + + ofFromStr = Node.fromString("0xDEADBEEFCAFE0001"); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + + ofFromStr = Node.fromString("DE:AD:BE:EF:CA:FE:00:01"); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + + ofFromStr = Node.fromString("de:ad:be:ef:ca:fe:00:01"); + + // Make sure we got a node + Assert.assertTrue(ofFromStr != null); + + // Now the converted node need to be the same of the + // original one + Assert.assertTrue(of.equals(ofFromStr)); + } catch (ConstructionException e) { + // If we reach this point the exception was raised + // which is not expected + Assert.assertTrue(false); + } + } + + @Test + public void testExtensibleNode() { + // Add a new ID type + Assert.assertTrue(Node.NodeIDType.registerIDType("FOO", Integer.class)); + + // Trying to re-register the node must fail + Assert.assertFalse(Node.NodeIDType.registerIDType("FOO", + Integer.class)); + try { + Node n = new Node("FOO", new Integer(0xCAFE)); + + System.out.println("Got Extended node:" + n); + } catch (ConstructionException e) { + // Got an unexpected exception + Assert.assertTrue(false); + } + + // Now unregister the type and make sure the node doesn't get + // created + Node.NodeIDType.unRegisterIDType("FOO"); + try { + Node n = new Node("FOO", new Integer(0xCAFE)); + + // If we reach here, something didn't go fine, an + // exception should have been raised + Assert.assertTrue(false); + } catch (ConstructionException e) { + // Got an expected exception, do nothing! + } + + Assert.assertTrue(true); + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/PathTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/PathTest.java new file mode 100644 index 0000000000..9058156b9e --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/PathTest.java @@ -0,0 +1,341 @@ + +/* + * 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 + */ + +/** + * @file PathTest.java + * + * @brief Unit Tests for Path element + * + * Unit Tests for Path element + */ +package org.opendaylight.controller.sal.core; + +import java.util.LinkedList; +import java.util.List; +import java.util.Arrays; +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Edge; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Path; + +public class PathTest { + @Test + public void testPathValid() { + List edges = null; + try { + Node n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c0 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x4), n0); + + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n1); + NodeConnector c2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0xCAFE), n1); + + Node n2 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector c3 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardOF1"), n2); + NodeConnector c4 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n2); + + Node n3 = new Node(Node.NodeIDType.ONEPK, new String("Router2")); + NodeConnector c5 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n3); + + Edge e0 = new Edge(c0, c1); + Edge e1 = new Edge(c1, c2); + Edge e2 = new Edge(c2, c3); + Edge e3 = new Edge(c3, c4); + Edge e4 = new Edge(c4, c5); + edges = new LinkedList(Arrays.asList(e0, e1, e2, e3, e4)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Path res = new Path(edges); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + // Now lets disconnect on edge so to create a disconnected + // path, the constructor should catch that and should not + // create the path + edges.remove(2); + + try { + Path res = new Path(edges); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + } + + @Test + public void testPathComparison() { + List edges1 = null; + Path path1 = null; + List edges2 = null; + Path path2 = null; + List edges3 = null; + Path path3 = null; + + try { + Node n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c0 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x4), n0); + + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n1); + NodeConnector c2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0xCAFE), n1); + + Node n2 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector c3 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardOF1"), n2); + NodeConnector c4 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n2); + + Node n3 = new Node(Node.NodeIDType.ONEPK, new String("Router2")); + NodeConnector c5 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n3); + + Edge e0 = new Edge(c0, c1); + Edge e1 = new Edge(c1, c2); + Edge e2 = new Edge(c2, c3); + Edge e3 = new Edge(c3, c4); + Edge e4 = new Edge(c4, c5); + edges1 = new LinkedList(Arrays.asList(e0, e1, e2, e3, e4)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c0 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x4), n0); + + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n1); + NodeConnector c2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0xCAFE), n1); + + Node n2 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector c3 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardOF1"), n2); + NodeConnector c4 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n2); + + Node n3 = new Node(Node.NodeIDType.ONEPK, new String("Router2")); + NodeConnector c5 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n3); + + Edge e0 = new Edge(c0, c1); + Edge e1 = new Edge(c1, c2); + Edge e2 = new Edge(c2, c3); + Edge e3 = new Edge(c3, c4); + Edge e4 = new Edge(c4, c5); + edges2 = new LinkedList(Arrays.asList(e0, e1, e2, e3, e4)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + Node n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c0 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x5), n0); + + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n1); + NodeConnector c2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0xCAFE), n1); + + Node n2 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector c3 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardOF1"), n2); + NodeConnector c4 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n2); + + Node n3 = new Node(Node.NodeIDType.ONEPK, new String("Router2")); + NodeConnector c5 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n3); + + Edge e0 = new Edge(c0, c1); + Edge e1 = new Edge(c1, c2); + Edge e2 = new Edge(c2, c3); + Edge e3 = new Edge(c3, c4); + Edge e4 = new Edge(c4, c5); + edges3 = new LinkedList(Arrays.asList(e0, e1, e2, e3, e4)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + path1 = new Path(edges1); + path2 = new Path(edges2); + path3 = new Path(edges3); + + System.out.println("Path1: " + path1); + System.out.println("Path2: " + path2); + System.out.println("Path3: " + path3); + + // Make sure the path are equals + Assert.assertTrue(path1.equals(path2)); + + // Make sure the path are marked as different + Assert.assertTrue(!path1.equals(path3)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + } + + @Test + public void testPathEmpty() { + try { + Path path = new Path(new LinkedList()); + // Exception is expected if not raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + } + + @Test + public void testPathOneElement() { + try { + Node n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c0 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x5), n0); + + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n1); + + Edge e0 = new Edge(c0, c1); + + Path path = new Path(new LinkedList(Arrays.asList(e0))); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + } + + @Test + public void testPathGetNodes() { + // Test on >2 edges paths + try { + Node n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c0 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x4), n0); + + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n1); + NodeConnector c2 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW2ONEPK, + new Short((short) 0xCAFE), n1); + + Node n2 = new Node(Node.NodeIDType.ONEPK, new String("Router1")); + NodeConnector c3 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK2OPENFLOW, + new String("towardOF1"), n2); + NodeConnector c4 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n2); + + Node n3 = new Node(Node.NodeIDType.ONEPK, new String("Router2")); + NodeConnector c5 = new NodeConnector( + NodeConnector.NodeConnectorIDType.ONEPK, new String( + "Gi1/0/1"), n3); + + Edge e0 = new Edge(c0, c1); + Edge e1 = new Edge(c1, c2); + Edge e2 = new Edge(c2, c3); + Edge e3 = new Edge(c3, c4); + Edge e4 = new Edge(c4, c5); + List edges = new LinkedList(Arrays.asList(e0, e1, e2, e3, e4)); + Path path = new Path(edges); + + // Test start node + Assert.assertTrue(path.getStartNode().equals(n0)); + + // Test end node + Assert.assertTrue(path.getEndNode().equals(n3)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + // Test on 1 edge path + try { + Node n0 = new Node(Node.NodeIDType.OPENFLOW, new Long(40L)); + NodeConnector c0 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x4), n0); + + Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L)); + NodeConnector c1 = new NodeConnector( + NodeConnector.NodeConnectorIDType.OPENFLOW, new Short( + (short) 0x1), n1); + + Edge e0 = new Edge(c0, c1); + List edges = new LinkedList(Arrays.asList(e0)); + Path path = new Path(edges); + + // Test start node + Assert.assertTrue(path.getStartNode().equals(n0)); + + // Test end node + Assert.assertTrue(path.getEndNode().equals(n1)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/PropertyTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/PropertyTest.java new file mode 100644 index 0000000000..8c2d38dc4c --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/core/PropertyTest.java @@ -0,0 +1,95 @@ + +/* + * 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 + */ + +/** + * @file PropertyTest.java + * + * @brief Test for properties + * + */ + +package org.opendaylight.controller.sal.core; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.core.Bandwidth; +import org.opendaylight.controller.sal.core.Latency; +import org.opendaylight.controller.sal.core.Property; + +public class PropertyTest { + @Test + public void testBandWidthStr() { + Property b; + + b = new Bandwidth(Bandwidth.BWUNK); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[UnKnown]")); + + b = new Bandwidth(100L); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[100bps]")); + + b = new Bandwidth(Bandwidth.BW10Mbps); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[10Mbps]")); + + b = new Bandwidth(Bandwidth.BW100Mbps); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[100Mbps]")); + + b = new Bandwidth(Bandwidth.BW100Mbps); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[100Mbps]")); + + b = new Bandwidth(Bandwidth.BW1Gbps); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[1Gbps]")); + + b = new Bandwidth(Bandwidth.BW10Gbps); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[10Gbps]")); + + b = new Bandwidth(Bandwidth.BW40Gbps); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[40Gbps]")); + + b = new Bandwidth(Bandwidth.BW100Gbps); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[100Gbps]")); + + b = new Bandwidth(Bandwidth.BW100Gbps + 15L); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[100Gbps]")); + + b = new Bandwidth(Bandwidth.BW1Tbps); + System.out.println("b = " + b); + Assert.assertTrue(b.toString().equals("BandWidth[1Tbps]")); + } + + @Test + public void testLatencyStr() { + Property l; + + l = new Latency(Latency.LATENCYUNK); + System.out.println("l = " + l); + Assert.assertTrue(l.toString().equals("Latency[UnKnown]")); + + l = new Latency(Latency.LATENCY1ns); + System.out.println("l = " + l); + Assert.assertTrue(l.toString().equals("Latency[1nsec]")); + + l = new Latency(Latency.LATENCY1us); + System.out.println("l = " + l); + Assert.assertTrue(l.toString().equals("Latency[1usec]")); + + l = new Latency(Latency.LATENCY1ms); + System.out.println("l = " + l); + Assert.assertTrue(l.toString().equals("Latency[1msec]")); + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/flowprogrammer/FlowTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/flowprogrammer/FlowTest.java new file mode 100644 index 0000000000..84340577f5 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/flowprogrammer/FlowTest.java @@ -0,0 +1,221 @@ + +/* + * 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.controller.sal.flowprogrammer; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.action.Action; +import org.opendaylight.controller.sal.action.Controller; +import org.opendaylight.controller.sal.action.Flood; +import org.opendaylight.controller.sal.action.Loopback; +import org.opendaylight.controller.sal.action.Output; +import org.opendaylight.controller.sal.action.PopVlan; +import org.opendaylight.controller.sal.action.PushVlan; +import org.opendaylight.controller.sal.action.SetDlDst; +import org.opendaylight.controller.sal.action.SetNwDst; +import org.opendaylight.controller.sal.action.SetVlanId; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.flowprogrammer.Flow; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; +import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.IPProtocols; +import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.opendaylight.controller.sal.utils.NodeCreator; + +public class FlowTest { + + @Test + public void testFlowEquality() throws Exception { + Node node = NodeCreator.createOFNode(1055l); + Flow flow1 = getSampleFlowV6(node); + Flow flow2 = getSampleFlowV6(node); + Flow flow3 = getSampleFlow(node); + + // Check Match equality + Assert.assertTrue(flow1.getMatch().equals(flow2.getMatch())); + + // Check Actions equality + for (int i = 0; i < flow1.getActions().size(); i++) { + Action a = flow1.getActions().get(i); + Action b = flow2.getActions().get(i); + Assert.assertTrue(a != b); + Assert.assertTrue(a.equals(b)); + } + + Assert.assertTrue(flow1.equals(flow2)); + Assert.assertFalse(flow2.equals(flow3)); + + // Check Flow equality where Flow has null action list (pure match) + List emptyList = new ArrayList(1); + Flow x = flow1.clone(); + x.setActions(emptyList); + Assert.assertFalse(flow1.equals(x)); + flow1.setActions(emptyList); + Assert.assertTrue(flow1.equals(x)); + } + + @Test + public void testFlowCloning() throws UnknownHostException { + Node node = NodeCreator.createOFNode(55l); + Flow flow1 = getSampleFlowV6(node); + Flow flow2 = flow1.clone(); + + Assert.assertTrue(flow1.equals(flow2)); + Assert.assertTrue(flow1.getMatch().equals(flow2.getMatch())); + Assert.assertTrue(flow1.getActions() != flow2.getActions()); + Assert.assertTrue(flow1.getActions().equals(flow2.getActions())); + } + + @Test + public void testFlowActions() throws UnknownHostException { + Node node = NodeCreator.createOFNode(55l); + Flow flow = getSampleFlowV6(node); + + List actions = flow.getActions(); + actions.add(new Loopback()); + + Assert.assertTrue(flow.getActions() != actions); + Assert.assertTrue(!flow.getActions().equals(actions)); + + flow.addAction(new Loopback()); + Assert.assertTrue(flow.getActions().equals(actions)); + + actions.remove(new Loopback()); + flow.removeAction(new Loopback()); + Assert.assertTrue(flow.getActions().equals(actions)); + + // Add a malformed action + Assert.assertFalse(flow.addAction(new PushVlan(EtherTypes.CISCOQINQ, 3, + 3, 8000))); + } + + private Flow getSampleFlow(Node node) throws UnknownHostException { + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + NodeConnector oport = NodeConnectorCreator.createOFNodeConnector( + (short) 30, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress.getByName("172.28.30.50"); + InetAddress dstIP = InetAddress.getByName("171.71.9.52"); + InetAddress newIP = InetAddress.getByName("200.200.100.1"); + InetAddress ipMask = InetAddress.getByName("255.255.255.0"); + InetAddress ipMask2 = InetAddress.getByName("255.240.0.0"); + short ethertype = EtherTypes.IPv4.shortValue(); + short vlan = (short) 27; + byte vlanPr = 3; + Byte tos = 4; + byte proto = IPProtocols.TCP.byteValue(); + short src = (short) 55000; + short dst = 80; + + /* + * Create a SAL Flow aFlow + */ + Match match = new Match(); + match.setField(MatchType.IN_PORT, port); + match.setField(MatchType.DL_SRC, srcMac); + match.setField(MatchType.DL_DST, dstMac); + match.setField(MatchType.DL_TYPE, ethertype); + match.setField(MatchType.DL_VLAN, vlan); + match.setField(MatchType.DL_VLAN_PR, vlanPr); + match.setField(MatchType.NW_SRC, srcIP, ipMask); + match.setField(MatchType.NW_DST, dstIP, ipMask2); + match.setField(MatchType.NW_TOS, tos); + match.setField(MatchType.NW_PROTO, proto); + match.setField(MatchType.TP_SRC, src); + match.setField(MatchType.TP_DST, dst); + + List actions = new ArrayList(); + actions.add(new SetNwDst(newIP)); + actions.add(new Output(oport)); + actions.add(new PopVlan()); + actions.add(new Flood()); + actions.add(new Controller()); + + Flow flow = new Flow(match, actions); + flow.setPriority((short) 100); + flow.setHardTimeout((short) 360); + + return flow; + } + + private Flow getSampleFlowV6(Node node) throws UnknownHostException { + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + NodeConnector oport = NodeConnectorCreator.createOFNodeConnector( + (short) 30, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + byte newMac[] = { (byte) 0x11, (byte) 0xaa, (byte) 0xbb, (byte) 0x34, + (byte) 0x9a, (byte) 0xee }; + InetAddress srcIP = InetAddress + .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress + .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMask = InetAddress + .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMask2 = InetAddress + .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + InetAddress newIP = InetAddress.getByName("2056:650::a1b0"); + short ethertype = EtherTypes.IPv6.shortValue(); + short vlan = (short) 27; + byte vlanPr = (byte) 3; + Byte tos = 4; + byte proto = IPProtocols.UDP.byteValue(); + short src = (short) 5500; + short dst = 80; + + /* + * Create a SAL Flow aFlow + */ + Match match = new Match(); + match.setField(MatchType.IN_PORT, port); + match.setField(MatchType.DL_SRC, srcMac); + match.setField(MatchType.DL_DST, dstMac); + match.setField(MatchType.DL_TYPE, ethertype); + match.setField(MatchType.DL_VLAN, vlan); + match.setField(MatchType.DL_VLAN_PR, vlanPr); + match.setField(MatchType.NW_SRC, srcIP, ipMask); + match.setField(MatchType.NW_DST, dstIP, ipMask2); + match.setField(MatchType.NW_TOS, tos); + match.setField(MatchType.NW_PROTO, proto); + match.setField(MatchType.TP_SRC, src); + match.setField(MatchType.TP_DST, dst); + + List actions = new ArrayList(); + actions.add(new Controller()); + actions.add(new SetVlanId(5)); + actions.add(new SetDlDst(newMac)); + actions.add(new SetNwDst(newIP)); + actions.add(new Output(oport)); + actions.add(new PopVlan()); + actions.add(new Flood()); + + actions.add(new Controller()); + + Flow flow = new Flow(match, actions); + flow.setPriority((short) 300); + flow.setHardTimeout((short) 240); + + return flow; + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java new file mode 100644 index 0000000000..722f993518 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java @@ -0,0 +1,449 @@ + +/* + * 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.controller.sal.match; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchField; +import org.opendaylight.controller.sal.match.MatchType; +import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.IPProtocols; +import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.opendaylight.controller.sal.utils.NodeCreator; + +public class MatchTest { + @Test + public void testMatchCreation() { + Node node = NodeCreator.createOFNode(7l); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 6, node); + MatchField field = new MatchField(MatchType.IN_PORT, port); + + Assert.assertTrue(field != null); + Assert.assertTrue(field.getType() == MatchType.IN_PORT); + Assert.assertTrue((NodeConnector) field.getValue() == port); + Assert.assertTrue(field.isValid()); + + field = null; + field = new MatchField(MatchType.TP_SRC, Long.valueOf(23)); + Assert.assertFalse(field.isValid()); + + field = null; + field = new MatchField(MatchType.TP_SRC, (long) 45); + Assert.assertFalse(field.isValid()); + + field = null; + field = new MatchField(MatchType.TP_SRC, 120000); + Assert.assertFalse(field.isValid()); + + byte mac[] = { (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, + (byte) 11, (byte) 22 }; + byte mask[] = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff }; + field = null; + field = new MatchField(MatchType.DL_SRC, mac, mask); + Assert.assertFalse(field.getValue() == null); + + field = null; + field = new MatchField(MatchType.NW_TOS, (byte) 0x22, (byte) 0x3); + Assert.assertFalse(field.getValue() == null); + } + + @Test + public void testMatchSetGet() { + Match x = new Match(); + short val = 2346; + NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector(val, + NodeCreator.createOFNode(1l)); + x.setField(MatchType.IN_PORT, inPort); + Assert.assertTrue(((NodeConnector) x.getField(MatchType.IN_PORT) + .getValue()).equals(inPort)); + Assert + .assertTrue((Short) ((NodeConnector) x.getField( + MatchType.IN_PORT).getValue()).getID() == val); + } + + @Test + public void testMatchSetGetMAC() { + Match x = new Match(); + byte mac[] = { (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, + (byte) 11, (byte) 22 }; + byte mac2[] = { (byte) 0xaa, (byte) 0xbb, 0, 0, 0, (byte) 0xbb }; + byte mask1[] = { (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, + (byte) 0x55, (byte) 0x66 }; + byte mask2[] = { (byte) 0xff, (byte) 0xff, (byte) 0, (byte) 0, + (byte) 0, (byte) 0xff }; + + x.setField(MatchType.DL_SRC, mac.clone(), mask1); + x.setField(MatchType.DL_DST, mac2.clone(), mask2); + Assert.assertTrue(Arrays.equals(mac, (byte[]) x.getField( + MatchType.DL_SRC).getValue())); + Assert.assertFalse(Arrays.equals((byte[]) x.getField(MatchType.DL_SRC) + .getValue(), (byte[]) x.getField(MatchType.DL_DST).getValue())); + Assert.assertFalse(x.getField(MatchType.DL_SRC).getBitMask() == x + .getField(MatchType.DL_DST).getBitMask()); + + x.setField(new MatchField(MatchType.DL_DST, mac.clone(), mask1)); + Assert.assertTrue(Arrays.equals((byte[]) x.getField(MatchType.DL_SRC) + .getValue(), (byte[]) x.getField(MatchType.DL_DST).getValue())); + } + + @Test + public void testMatchSetGetNWAddr() throws UnknownHostException { + Match x = new Match(); + String ip = "172.20.231.23"; + InetAddress address = InetAddress.getByName(ip); + InetAddress mask = InetAddress.getByName("255.255.0.0"); + + x.setField(MatchType.NW_SRC, address, mask); + Assert.assertTrue(ip.equals(((InetAddress) x.getField(MatchType.NW_SRC) + .getValue()).getHostAddress())); + Assert.assertTrue(x.getField(MatchType.NW_SRC).getMask().equals(mask)); + } + + @Test + public void testMatchSetGetEtherType() throws UnknownHostException { + Match x = new Match(); + + x.setField(MatchType.DL_TYPE, EtherTypes.QINQ.shortValue(), + (short) 0xffff); + Assert.assertTrue(((Short) x.getField(MatchType.DL_TYPE).getValue()) + .equals(EtherTypes.QINQ.shortValue())); + Assert + .assertFalse(x.getField(MatchType.DL_TYPE).getValue() == EtherTypes.QINQ); + Assert.assertFalse(x.getField(MatchType.DL_TYPE).getValue().equals( + EtherTypes.QINQ)); + + x.setField(MatchType.DL_TYPE, EtherTypes.LLDP.shortValue(), + (short) 0xffff); + Assert.assertTrue(((Short) x.getField(MatchType.DL_TYPE).getValue()) + .equals(EtherTypes.LLDP.shortValue())); + Assert.assertFalse(x.getField(MatchType.DL_TYPE).equals( + EtherTypes.LLDP.intValue())); + } + + @Test + public void testSetGetNwTos() { + Match x = new Match(); + x.setField(MatchType.NW_TOS, (byte) 0xb, (byte) 0xf); + + Byte t = new Byte((byte) 0xb); + + Object o = x.getField(MatchType.NW_TOS).getValue(); + Assert.assertTrue(o.equals(t)); + Assert.assertTrue(o.equals((byte) 0xb)); + } + + @Test + public void testSetGetNwProto() { + Match x = new Match(); + byte proto = (byte) 199; + x.setField(MatchType.NW_PROTO, proto, (byte) 0xff); + + Object o = x.getField(MatchType.NW_PROTO).getValue(); + Assert.assertTrue(o.equals(proto)); + } + + @Test + public void testMatchMask() { + Match x = new Match(); + NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector( + (short) 6, NodeCreator.createOFNode(3l)); + x.setField(MatchType.IN_PORT, inPort); + x.setField(MatchType.DL_VLAN, (short) 28, (short) 0xfff); + Assert.assertFalse(x.getMatches() == 0); + Assert + .assertTrue(x.getMatches() == (MatchType.IN_PORT.getIndex() | MatchType.DL_VLAN + .getIndex())); + } + + @Test + public void testMatchBitMask() { + byte mac[] = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 22, (byte) 12 }; + byte mask[] = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0 }; + NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector( + (short) 4095, NodeCreator.createOFNode(7l)); + + MatchField x = new MatchField(MatchType.IN_PORT, inPort); + Assert.assertTrue((x.getMask()) == null); + + x = new MatchField(MatchType.DL_VLAN, (short) 255, (short) 0xff); + Assert.assertTrue(x.getBitMask() == 0xff); + + x = new MatchField(MatchType.DL_SRC, mac, mask); + Assert.assertTrue(x.getMask().equals(mask)); + Assert.assertTrue(x.getBitMask() == 0xffffffffff00L); + } + + @Test + public void testNullMask() { + byte mac[] = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 22, (byte) 12 }; + NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector( + (short) 2000, NodeCreator.createOFNode(7l)); + + MatchField x = new MatchField(MatchType.IN_PORT, inPort); + Assert.assertTrue(x.getBitMask() == 0); + + x = new MatchField(MatchType.NW_PROTO, (byte) 17); + Assert.assertTrue(x.getBitMask() == 0xff); + + x = new MatchField(MatchType.DL_VLAN, (short) 255); + Assert.assertTrue(x.getBitMask() == 0xfff); + + x = new MatchField(MatchType.DL_SRC, mac); + Assert.assertTrue(x.getBitMask() == 0xffffffffffffL); + } + + @Test + public void testEquality() throws Exception { + Node node = NodeCreator.createOFNode(7l); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + NodeConnector port2 = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + byte srcMac2[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac2[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress + .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress + .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMask = InetAddress + .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMaskd = InetAddress + .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + InetAddress srcIP2 = InetAddress + .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP2 = InetAddress + .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMask2 = InetAddress + .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMaskd2 = InetAddress + .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + short ethertype = EtherTypes.IPv6.shortValue(); + short ethertype2 = EtherTypes.IPv6.shortValue(); + short vlan = (short) 27, vlan2 = (short) 27; + byte vlanPr = (byte) 3, vlanPr2 = (byte) 3; + Byte tos = 4, tos2 = 4; + byte proto = IPProtocols.UDP.byteValue(), proto2 = IPProtocols.UDP + .byteValue(); + short src = (short) 5500, src2 = (short) 5500; + short dst = 80, dst2 = 80; + + /* + * Create a SAL Flow aFlow + */ + Match match1 = new Match(); + Match match2 = new Match(); + match1.setField(MatchType.IN_PORT, port); + match1.setField(MatchType.DL_SRC, srcMac); + match1.setField(MatchType.DL_DST, dstMac); + match1.setField(MatchType.DL_TYPE, ethertype); + match1.setField(MatchType.DL_VLAN, vlan); + match1.setField(MatchType.DL_VLAN_PR, vlanPr); + match1.setField(MatchType.NW_SRC, srcIP, ipMask); + match1.setField(MatchType.NW_DST, dstIP, ipMaskd); + match1.setField(MatchType.NW_TOS, tos); + match1.setField(MatchType.NW_PROTO, proto); + match1.setField(MatchType.TP_SRC, src); + match1.setField(MatchType.TP_DST, dst); + + match2.setField(MatchType.IN_PORT, port2); + match2.setField(MatchType.DL_SRC, srcMac2); + match2.setField(MatchType.DL_DST, dstMac2); + match2.setField(MatchType.DL_TYPE, ethertype2); + match2.setField(MatchType.DL_VLAN, vlan2); + match2.setField(MatchType.DL_VLAN_PR, vlanPr2); + match2.setField(MatchType.NW_SRC, srcIP2, ipMask2); + match2.setField(MatchType.NW_DST, dstIP2, ipMaskd2); + match2.setField(MatchType.NW_TOS, tos2); + match2.setField(MatchType.NW_PROTO, proto2); + match2.setField(MatchType.TP_SRC, src2); + match2.setField(MatchType.TP_DST, dst2); + + Assert.assertTrue(match1.equals(match2)); + + // Make sure all values are equals + for (MatchType type : MatchType.values()) { + if (match1.isPresent(type)) { + Assert.assertTrue(match1.getField(type).equals( + match2.getField(type))); + } + } + + // Make none of the fields couples are pointing to the same reference + MatchField a = null, b = null; + for (MatchType type : MatchType.values()) { + a = match1.getField(type); + b = match2.getField(type); + if (a != null && b != null) { + Assert.assertFalse(a == b); + } + } + } + + @Test + public void testCloning() throws Exception { + Node node = NodeCreator.createOFNode(7l); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress + .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress + .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMasks = InetAddress + .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMaskd = InetAddress + .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + short ethertype = EtherTypes.IPv6.shortValue(); + short vlan = (short) 27; + byte vlanPr = (byte) 3; + Byte tos = 4; + byte proto = IPProtocols.UDP.byteValue(); + short src = (short) 5500; + short dst = 80; + + /* + * Create a SAL Flow aFlow + */ + Match match = new Match(); + match.setField(MatchType.IN_PORT, port); + match.setField(MatchType.DL_SRC, srcMac); + match.setField(MatchType.DL_DST, dstMac); + match.setField(MatchType.DL_TYPE, ethertype); + match.setField(MatchType.DL_VLAN, vlan); + match.setField(MatchType.DL_VLAN_PR, vlanPr); + match.setField(MatchType.NW_SRC, srcIP, ipMasks); + match.setField(MatchType.NW_DST, dstIP, ipMaskd); + match.setField(MatchType.NW_TOS, tos); + match.setField(MatchType.NW_PROTO, proto); + match.setField(MatchType.TP_SRC, src); + match.setField(MatchType.TP_DST, dst); + + Match cloned = match.clone(); + + // Make sure all values are equals + for (MatchType type : MatchType.values()) { + if (match.isPresent(type)) { + if (!match.getField(type).equals(cloned.getField(type))) { + Assert.assertTrue(match.getField(type).equals( + cloned.getField(type))); + } + } + } + + // Make sure none of the fields couples are pointing to the same reference + MatchField a = null, b = null; + for (MatchType type : MatchType.values()) { + a = match.getField(type); + b = cloned.getField(type); + if (a != null && b != null) { + Assert.assertFalse(a == b); + } + } + + Assert.assertTrue(match.equals(cloned)); + + Assert.assertFalse(match.getField(MatchType.DL_SRC) == cloned + .getField(MatchType.DL_SRC)); + Assert.assertFalse(match.getField(MatchType.NW_DST) == cloned + .getField(MatchType.NW_DST)); + Assert.assertTrue(match.getField(MatchType.NW_DST).getMask().equals( + cloned.getField(MatchType.NW_DST).getMask())); + } + + @Test + public void testFlip() throws Exception { + Node node = NodeCreator.createOFNode(7l); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress + .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress + .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMasks = InetAddress + .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMaskd = InetAddress + .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + short ethertype = EtherTypes.IPv6.shortValue(); + short vlan = (short) 27; + byte vlanPr = (byte) 3; + Byte tos = 4; + byte proto = IPProtocols.UDP.byteValue(); + short src = (short) 5500; + short dst = 80; + + /* + * Create a SAL Flow aFlow + */ + Match match = new Match(); + match.setField(MatchType.IN_PORT, port); + match.setField(MatchType.DL_SRC, srcMac); + match.setField(MatchType.DL_DST, dstMac); + match.setField(MatchType.DL_TYPE, ethertype); + match.setField(MatchType.DL_VLAN, vlan); + match.setField(MatchType.DL_VLAN_PR, vlanPr); + match.setField(MatchType.NW_SRC, srcIP, ipMasks); + match.setField(MatchType.NW_DST, dstIP, ipMaskd); + match.setField(MatchType.NW_TOS, tos); + match.setField(MatchType.NW_PROTO, proto); + match.setField(MatchType.TP_SRC, src); + match.setField(MatchType.TP_DST, dst); + + Match flipped = match.reverse(); + + Assert.assertTrue(match.getField(MatchType.DL_TYPE).equals( + flipped.getField(MatchType.DL_TYPE))); + Assert.assertTrue(match.getField(MatchType.DL_VLAN).equals( + flipped.getField(MatchType.DL_VLAN))); + + Assert.assertTrue(match.getField(MatchType.DL_DST).getValue().equals( + flipped.getField(MatchType.DL_SRC).getValue())); + Assert.assertTrue(match.getField(MatchType.DL_DST).getMask() == flipped + .getField(MatchType.DL_SRC).getMask()); + + Assert.assertTrue(match.getField(MatchType.NW_DST).getValue().equals( + flipped.getField(MatchType.NW_SRC).getValue())); + Assert.assertTrue(match.getField(MatchType.NW_DST).getMask() == flipped + .getField(MatchType.NW_SRC).getMask()); + + Assert.assertTrue(match.getField(MatchType.TP_DST).getValue().equals( + flipped.getField(MatchType.TP_SRC).getValue())); + Assert.assertTrue(match.getField(MatchType.TP_DST).getMask() == flipped + .getField(MatchType.TP_SRC).getMask()); + + Match flipflip = flipped.reverse().reverse(); + Assert.assertTrue(flipflip.equals(flipped)); + + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ARPTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ARPTest.java new file mode 100644 index 0000000000..a51f448a2d --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ARPTest.java @@ -0,0 +1,227 @@ + +/* + * 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.controller.sal.packet; + +import org.junit.Test; +import org.opendaylight.controller.sal.packet.ARP; + +import junit.framework.Assert; + +public class ARPTest { + + @Test + public void testGetHardwareType() { + ARP arp = new ARP(); + byte[] hardwaretype = { 8, 6 }; + arp.hdrFieldsMap.put("HardwareType", hardwaretype); + short hwtype = arp.getHardwareType(); + Assert.assertTrue(hwtype == 2054); + } + + @Test + public void testGetProtocolType() { + ARP arp = new ARP(); + byte[] protocoltype = { 8, 0 }; + arp.hdrFieldsMap.put("ProtocolType", protocoltype); + short ptype = arp.getProtocolType(); + Assert.assertTrue(ptype == 2048); + } + + @Test + public void testGetHardwareAddressLength() { + ARP arp = new ARP(); + byte[] hardwareaddresslength = { 48 }; + arp.hdrFieldsMap.put("HardwareAddressLength", hardwareaddresslength); + byte hwaddrlength = arp.getHardwareAddressLength(); + Assert.assertTrue(hwaddrlength == 48); + } + + @Test + public void testGetProtocolAddressLength() { + ARP arp = new ARP(); + byte[] protocoladdresslength = { 32 }; + arp.hdrFieldsMap.put("ProtocolAddressLength", protocoladdresslength); + byte paddrlength = arp.getProtocolAddressLength(); + Assert.assertTrue(paddrlength == 32); + } + + @Test + public void testGetOpCode() { + ARP arp = new ARP(); + byte[] opcode = { 0, 2 }; + arp.hdrFieldsMap.put("OpCode", opcode); + short opCode = arp.getOpCode(); + Assert.assertTrue(opCode == 2); + } + + @Test + public void testGetSenderHardwareAddress() { + ARP arp = new ARP(); + byte[] hardwareaddress = { 48, 50, 120, 15, 66, 80 }; + arp.hdrFieldsMap.put("SenderHardwareAddress", hardwareaddress); + byte[] hwAddress = arp.getSenderHardwareAddress(); + Assert.assertTrue(hwAddress[0] == 48); + Assert.assertTrue(hwAddress[1] == 50); + Assert.assertTrue(hwAddress[2] == 120); + Assert.assertTrue(hwAddress[3] == 15); + Assert.assertTrue(hwAddress[4] == 66); + Assert.assertTrue(hwAddress[5] == 80); + } + + @Test + public void testGetSenderProtocolAddress() { + ARP arp = new ARP(); + byte[] protocoladdress = { 50, 100, 10, 20, 40, 80 }; + arp.hdrFieldsMap.put("SenderProtocolAddress", protocoladdress); + byte[] pAddress = arp.getSenderProtocolAddress(); + Assert.assertTrue(pAddress[0] == 50); + Assert.assertTrue(pAddress[1] == 100); + Assert.assertTrue(pAddress[2] == 10); + Assert.assertTrue(pAddress[3] == 20); + Assert.assertTrue(pAddress[4] == 40); + Assert.assertTrue(pAddress[5] == 80); + } + + @Test + public void testGetTargetHardwareAddress() { + ARP arp = new ARP(); + byte[] hardwareaddress = { 48, 50, 120, 15, 66, 80 }; + arp.hdrFieldsMap.put("TargetHardwareAddress", hardwareaddress); + byte[] hwAddress = arp.getTargetHardwareAddress(); + Assert.assertTrue(hwAddress[0] == 48); + Assert.assertTrue(hwAddress[1] == 50); + Assert.assertTrue(hwAddress[2] == 120); + Assert.assertTrue(hwAddress[3] == 15); + Assert.assertTrue(hwAddress[4] == 66); + Assert.assertTrue(hwAddress[5] == 80); + } + + @Test + public void testGetTargetProtocolAddress() { + ARP arp = new ARP(); + byte[] protocoladdress = { 50, 100, 10, 20, 40, 80 }; + arp.hdrFieldsMap.put("TargetProtocolAddress", protocoladdress); + byte[] pAddress = arp.getTargetProtocolAddress(); + Assert.assertTrue(pAddress[0] == 50); + Assert.assertTrue(pAddress[1] == 100); + Assert.assertTrue(pAddress[2] == 10); + Assert.assertTrue(pAddress[3] == 20); + Assert.assertTrue(pAddress[4] == 40); + Assert.assertTrue(pAddress[5] == 80); + } + + @Test + public void testSetHardwareType() { + ARP arp = new ARP(); + short hwtype = 2054; + arp.setHardwareType(hwtype); + byte[] hardwaretype = arp.hdrFieldsMap.get("HardwareType"); + Assert.assertTrue(hardwaretype[0] == 8); + Assert.assertTrue(hardwaretype[1] == 6); + } + + @Test + public void testSetProtocolType() { + ARP arp = new ARP(); + short ptype = 2048; + arp.setProtocolType(ptype); + byte[] protocoltype = arp.hdrFieldsMap.get("ProtocolType"); + Assert.assertTrue(protocoltype[0] == 8); + Assert.assertTrue(protocoltype[1] == 0); + } + + @Test + public void testSetHardwareAddressLength() { + ARP arp = new ARP(); + byte hwaddrlength = 48; + arp.setHardwareAddressLength(hwaddrlength); + byte[] hardwareaddresslength = arp.hdrFieldsMap + .get("HardwareAddressLength"); + Assert.assertTrue(hardwareaddresslength[0] == 48); + } + + @Test + public void testSetProtocolAddressLength() { + ARP arp = new ARP(); + byte PAddrlength = 32; + arp.setProtocolAddressLength(PAddrlength); + byte[] protocoladdresslength = arp.hdrFieldsMap + .get("ProtocolAddressLength"); + Assert.assertTrue(protocoladdresslength[0] == 32); + } + + @Test + public void testSetOpCode() { + ARP arp = new ARP(); + short opCode = (short) 2; + arp.setOpCode(opCode); + byte[] opcode = arp.hdrFieldsMap.get("OpCode"); + //System.out.println(opCode); + Assert.assertTrue(opcode[0] == 0); + Assert.assertTrue(opcode[1] == 2); + } + + @Test + public void testSetSenderHardwareAddress() { + ARP arp = new ARP(); + byte[] hardwareaddress = { 48, 50, 120, 15, 66, 80 }; + arp.setSenderHardwareAddress(hardwareaddress); + byte[] hwAddress = arp.hdrFieldsMap.get("SenderHardwareAddress"); + Assert.assertTrue(hwAddress[0] == 48); + Assert.assertTrue(hwAddress[1] == 50); + Assert.assertTrue(hwAddress[2] == 120); + Assert.assertTrue(hwAddress[3] == 15); + Assert.assertTrue(hwAddress[4] == 66); + Assert.assertTrue(hwAddress[5] == 80); + } + + @Test + public void testSetSenderProtocolAddress() { + ARP arp = new ARP(); + byte[] protocoladdress = { 50, 100, 10, 20, 40, 80 }; + arp.setSenderProtocolAddress(protocoladdress); + byte[] pAddress = arp.hdrFieldsMap.get("SenderProtocolAddress"); + Assert.assertTrue(pAddress[0] == 50); + Assert.assertTrue(pAddress[1] == 100); + Assert.assertTrue(pAddress[2] == 10); + Assert.assertTrue(pAddress[3] == 20); + Assert.assertTrue(pAddress[4] == 40); + Assert.assertTrue(pAddress[5] == 80); + } + + @Test + public void testSetTargetHardwareAddress() { + ARP arp = new ARP(); + byte[] hardwareaddress = { 48, 50, 120, 15, 66, 80 }; + arp.setTargetHardwareAddress(hardwareaddress); + byte[] hwAddress = arp.hdrFieldsMap.get("TargetHardwareAddress"); + Assert.assertTrue(hwAddress[0] == 48); + Assert.assertTrue(hwAddress[1] == 50); + Assert.assertTrue(hwAddress[2] == 120); + Assert.assertTrue(hwAddress[3] == 15); + Assert.assertTrue(hwAddress[4] == 66); + Assert.assertTrue(hwAddress[5] == 80); + } + + @Test + public void testSetTargetProtocolAddress() { + ARP arp = new ARP(); + byte[] protocoladdress = { 50, 100, 10, 20, 40, 80 }; + arp.setTargetProtocolAddress(protocoladdress); + byte[] pAddress = arp.hdrFieldsMap.get("TargetProtocolAddress"); + Assert.assertTrue(pAddress[0] == 50); + Assert.assertTrue(pAddress[1] == 100); + Assert.assertTrue(pAddress[2] == 10); + Assert.assertTrue(pAddress[3] == 20); + Assert.assertTrue(pAddress[4] == 40); + Assert.assertTrue(pAddress[5] == 80); + } + +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/BitBufferHelperTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/BitBufferHelperTest.java new file mode 100644 index 0000000000..b1c5e945d6 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/BitBufferHelperTest.java @@ -0,0 +1,693 @@ + +/* + * 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.controller.sal.packet; + +import junit.framework.Assert; + +import org.junit.Test; +import org.opendaylight.controller.sal.packet.BitBufferHelper; + +public class BitBufferHelperTest { + + @Test + public void testGetByte() { + byte[] data = { 100 }; + Assert.assertTrue(BitBufferHelper.getByte(data) == 100); + } + + @Test + public void testGetBits() throws Exception { + byte[] data = { 10, 12, 14, 20, 55, 69, 82, 97, 109, 117, 127, -50 }; + byte[] bits; + + bits = BitBufferHelper.getBits(data, 88, 8); //BYTE extraOffsetBits = extranumBits = 0 + Assert.assertTrue(bits[0] == -50); + + bits = BitBufferHelper.getBits(data, 8, 16); //Short + Assert.assertTrue(bits[0] == 12); + Assert.assertTrue(bits[1] == 14); + + bits = BitBufferHelper.getBits(data, 32, 32); //Int + Assert.assertTrue(bits[0] == 55); + Assert.assertTrue(bits[1] == 69); + Assert.assertTrue(bits[2] == 82); + Assert.assertTrue(bits[3] == 97); + + bits = BitBufferHelper.getBits(data, 16, 48); //Long + Assert.assertTrue(bits[0] == 14); + Assert.assertTrue(bits[1] == 20); + Assert.assertTrue(bits[2] == 55); + Assert.assertTrue(bits[3] == 69); + Assert.assertTrue(bits[4] == 82); + Assert.assertTrue(bits[5] == 97); + + bits = BitBufferHelper.getBits(data, 40, 7); //BYTE extraOffsetBits = extranumBits != 0 + Assert.assertTrue(bits[0] == 34); + + bits = BitBufferHelper.getBits(data, 8, 13); //Short + Assert.assertTrue(bits[0] == 1); + Assert.assertTrue(bits[1] == -127); + + bits = BitBufferHelper.getBits(data, 32, 28); //Int + Assert.assertTrue(bits[0] == 3); + Assert.assertTrue(bits[1] == 116); + Assert.assertTrue(bits[2] == 85); + Assert.assertTrue(bits[3] == 38); + + bits = BitBufferHelper.getBits(data, 16, 41); //Long + Assert.assertTrue(bits[0] == 0); + Assert.assertTrue(bits[1] == 28); + Assert.assertTrue(bits[2] == 40); + Assert.assertTrue(bits[3] == 110); + Assert.assertTrue(bits[4] == -118); + Assert.assertTrue(bits[5] == -92); + + bits = BitBufferHelper.getBits(data, 3, 7); //BYTE extraOffsetBits != 0; extranumBits == 0 + Assert.assertTrue(bits[0] == 40); + + bits = BitBufferHelper.getBits(data, 13, 16); //Short + Assert.assertTrue(bits[0] == -127); + Assert.assertTrue(bits[1] == -62); + + bits = BitBufferHelper.getBits(data, 5, 32); //Int + Assert.assertTrue(bits[0] == 65); + Assert.assertTrue(bits[1] == -127); + Assert.assertTrue(bits[2] == -62); + Assert.assertTrue(bits[3] == -122); + + bits = BitBufferHelper.getBits(data, 23, 48); //Long + Assert.assertTrue(bits[0] == 10); + Assert.assertTrue(bits[1] == 27); + Assert.assertTrue(bits[2] == -94); + Assert.assertTrue(bits[3] == -87); + Assert.assertTrue(bits[4] == 48); + Assert.assertTrue(bits[5] == -74); + + bits = BitBufferHelper.getBits(data, 66, 9); //BYTE extraOffsetBits != 0; extranumBits != 0 + Assert.assertTrue(bits[0] == 1); + Assert.assertTrue(bits[1] == 107); + + bits = BitBufferHelper.getBits(data, 13, 15); //Short + Assert.assertTrue(bits[0] == 64); + Assert.assertTrue(bits[1] == -31); + + bits = BitBufferHelper.getBits(data, 5, 29); //Int + Assert.assertTrue(bits[0] == 8); + Assert.assertTrue(bits[1] == 48); + Assert.assertTrue(bits[2] == 56); + Assert.assertTrue(bits[3] == 80); + + bits = BitBufferHelper.getBits(data, 31, 43); //Long + Assert.assertTrue(bits[0] == 0); + Assert.assertTrue(bits[1] == -35); + Assert.assertTrue(bits[2] == 21); + Assert.assertTrue(bits[3] == 73); + Assert.assertTrue(bits[4] == -123); + Assert.assertTrue(bits[5] == -75); + + bits = BitBufferHelper.getBits(data, 4, 12); //Short + Assert.assertTrue(bits[0] == 10); + Assert.assertTrue(bits[1] == 12); + + byte[] data1 = { 0, 8 }; + bits = BitBufferHelper.getBits(data1, 7, 9); //Short + Assert.assertTrue(bits[0] == 0); + Assert.assertTrue(bits[1] == 8); + + byte[] data2 = { 2, 8 }; + bits = BitBufferHelper.getBits(data2, 0, 7); //Short + Assert.assertTrue(bits[0] == 1); + + bits = BitBufferHelper.getBits(data2, 7, 9); //Short + Assert.assertTrue(bits[0] == 0); + Assert.assertTrue(bits[1] == 8); + } + + // [01101100][01100000] + // [01100011] + @Test + public void testGetBytes() throws Exception { + byte data[] = { 108, 96, 125, -112, 5, 6, 108, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22 }; + byte[] x; + + Assert.assertTrue(BitBufferHelper.getBits(data, 0, 8)[0] == 108); + Assert.assertTrue(BitBufferHelper.getBits(data, 8, 8)[0] == 96); + + x = BitBufferHelper.getBits(data, 0, 10); + Assert.assertTrue(x[0] == 1); + Assert.assertTrue(x[1] == -79); + + x = BitBufferHelper.getBits(data, 3, 8); + Assert.assertTrue(x[0] == 99); + //Assert.assertTrue(x[1] == 97); + + } + + @Test + public void testMSBMask() { + int numBits = 1; //MSB + int mask = BitBufferHelper.getMSBMask(numBits); + Assert.assertTrue(mask == 128); + + numBits = 8; + mask = BitBufferHelper.getMSBMask(numBits); + Assert.assertTrue(mask == 255); + + numBits = 2; + mask = BitBufferHelper.getMSBMask(numBits); + Assert.assertTrue(mask == 192); + } + + @Test + public void testLSBMask() { + int numBits = 1; //LSB + int mask = BitBufferHelper.getLSBMask(numBits); + Assert.assertTrue(mask == 1); + + numBits = 3; + mask = BitBufferHelper.getLSBMask(numBits); + Assert.assertTrue(mask == 7); + + numBits = 8; + mask = BitBufferHelper.getLSBMask(numBits); + Assert.assertTrue(mask == 255); + } + + @Test + public void testToByteArray() { + short sh = Short.MAX_VALUE; + byte[] data_sh = new byte[Byte.SIZE / 8]; + data_sh = BitBufferHelper.toByteArray(sh); + Assert.assertTrue(data_sh[0] == 127); + Assert.assertTrue(data_sh[1] == -1); + + short sh2 = Short.MIN_VALUE; + byte[] data_sh2 = new byte[Byte.SIZE / 8]; + data_sh2 = BitBufferHelper.toByteArray(sh2); + Assert.assertTrue(data_sh2[0] == -128); + Assert.assertTrue(data_sh2[1] == 0); + + short sh3 = 16384; + byte[] data_sh3 = new byte[Byte.SIZE / 8]; + data_sh3 = BitBufferHelper.toByteArray(sh3); + Assert.assertTrue(data_sh3[0] == 64); + Assert.assertTrue(data_sh3[1] == 0); + + short sh4 = 146; //TCP headerlenflags - startoffset = 103 + byte[] data_sh4 = new byte[Byte.SIZE / 8]; + data_sh4 = BitBufferHelper.toByteArray(sh4); + Assert.assertTrue(data_sh4[0] == 0); + Assert.assertTrue(data_sh4[1] == -110); + + short sh4_2 = 5000; //IPv4 Offset - startOffset = 51 (to 63) + byte[] data_sh4_2 = new byte[Byte.SIZE / 8]; + data_sh4_2 = BitBufferHelper.toByteArray(sh4_2); + Assert.assertTrue(data_sh4_2[0] == 19); + Assert.assertTrue(data_sh4_2[1] == -120); + + short sh4_3 = 5312; //numEndRestBits < numBitstoShiftBy + byte[] data_sh4_3 = new byte[Byte.SIZE / 8]; + data_sh4_3 = BitBufferHelper.toByteArray(sh4_3); + Assert.assertTrue(data_sh4_3[0] == 20); + Assert.assertTrue(data_sh4_3[1] == -64); + + int Int = Integer.MAX_VALUE; + byte[] data_Int = new byte[Integer.SIZE / 8]; + data_Int = BitBufferHelper.toByteArray(Int); + Assert.assertTrue(data_Int[0] == 127); + Assert.assertTrue(data_Int[1] == -1); + Assert.assertTrue(data_Int[2] == -1); + Assert.assertTrue(data_Int[3] == -1); + + int Int2 = Integer.MIN_VALUE; + byte[] data_Int2 = new byte[Integer.SIZE / 8]; + data_Int2 = BitBufferHelper.toByteArray(Int2); + Assert.assertTrue(data_Int2[0] == -128); + Assert.assertTrue(data_Int2[1] == 0); + Assert.assertTrue(data_Int2[2] == 0); + Assert.assertTrue(data_Int2[3] == 0); + + int Int3 = 1077952576; + byte[] data_Int3 = new byte[Integer.SIZE / 8]; + data_Int3 = BitBufferHelper.toByteArray(Int3); + Assert.assertTrue(data_Int3[0] == 64); + Assert.assertTrue(data_Int3[1] == 64); + Assert.assertTrue(data_Int3[2] == 64); + Assert.assertTrue(data_Int3[3] == 64); + + long Lng = Long.MAX_VALUE; + byte[] data_lng = new byte[Long.SIZE / 8]; + data_lng = BitBufferHelper.toByteArray(Lng); + Assert.assertTrue(data_lng[0] == 127); + Assert.assertTrue(data_lng[1] == -1); + Assert.assertTrue(data_lng[2] == -1); + Assert.assertTrue(data_lng[3] == -1); + Assert.assertTrue(data_lng[4] == -1); + Assert.assertTrue(data_lng[5] == -1); + Assert.assertTrue(data_lng[6] == -1); + Assert.assertTrue(data_lng[7] == -1); + + long Lng2 = Long.MIN_VALUE; + byte[] data_lng2 = new byte[Long.SIZE / 8]; + data_lng2 = BitBufferHelper.toByteArray(Lng2); + Assert.assertTrue(data_lng2[0] == -128); + Assert.assertTrue(data_lng2[1] == 0); + Assert.assertTrue(data_lng2[2] == 0); + Assert.assertTrue(data_lng2[3] == 0); + Assert.assertTrue(data_lng2[4] == 0); + Assert.assertTrue(data_lng2[5] == 0); + Assert.assertTrue(data_lng2[6] == 0); + Assert.assertTrue(data_lng2[7] == 0); + + byte B = Byte.MAX_VALUE; + byte[] data_B = new byte[Byte.SIZE / 8]; + data_B = BitBufferHelper.toByteArray(B); + Assert.assertTrue(data_B[0] == 127); + + byte B1 = Byte.MIN_VALUE; + byte[] data_B1 = new byte[Byte.SIZE / 8]; + data_B1 = BitBufferHelper.toByteArray(B1); + Assert.assertTrue(data_B1[0] == -128); + + byte B2 = 64; + byte[] data_B2 = new byte[Byte.SIZE / 8]; + data_B2 = BitBufferHelper.toByteArray(B2); + Assert.assertTrue(data_B2[0] == 64); + + byte B3 = 32; + byte[] data_B3 = new byte[Byte.SIZE / 8]; + data_B3 = BitBufferHelper.toByteArray(B3); + Assert.assertTrue(data_B3[0] == 32); + + } + + @Test + public void testToByteArrayVariable() { + int len = 9; + byte[] data_sh; + data_sh = BitBufferHelper.toByteArray(511, len); + Assert.assertTrue(data_sh[0] == (byte) 255); + Assert.assertTrue(data_sh[1] == (byte) 128); + + data_sh = BitBufferHelper.toByteArray((int) 511, len); + Assert.assertTrue(data_sh[0] == (byte) 255); + Assert.assertTrue(data_sh[1] == (byte) 128); + + data_sh = BitBufferHelper.toByteArray((long) 511, len); + Assert.assertTrue(data_sh[0] == (byte) 255); + Assert.assertTrue(data_sh[1] == (byte) 128); + } + + @Test + public void testToInt() { + byte data[] = { 1 }; + Assert.assertTrue(BitBufferHelper.toNumber(data) == 1); + + byte data2[] = { 1, 1 }; + Assert.assertTrue(BitBufferHelper.toNumber(data2) == 257); + + byte data3[] = { 1, 1, 1 }; + Assert.assertTrue(BitBufferHelper.toNumber(data3) == 65793); + } + + @Test + public void testToLongGetter() { + byte data[] = { 1, 1 }; + Assert.assertTrue(BitBufferHelper.getLong(data) == 257L); + } + + @Test + public void testSetByte() throws Exception { + byte input; + byte[] data = new byte[20]; + + input = 125; + BitBufferHelper.setByte(data, input, 0, Byte.SIZE); + Assert.assertTrue(data[0] == 125); + + input = 109; + BitBufferHelper.setByte(data, input, 152, Byte.SIZE); + Assert.assertTrue(data[19] == 109); + } + + @Test + public void testSetBytes() throws Exception { + byte[] input = { 0, 1 }; + byte[] data = { 6, 0 }; + + BitBufferHelper.setBytes(data, input, 7, 9); + Assert.assertTrue(data[0] == 6); + Assert.assertTrue(data[1] == 1); + } + + //@Test + //INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [10100000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001]*/ + public void testInsertBits() throws Exception { + //CASE 1: startOffset%8 == 0 && numBits%8 == 0 + byte inputdata[] = { 75, 110, 107, 80, 10, 12, 35, 100, 125, 65 }; + int startOffset = 0; + int numBits = 8; + + byte data1[] = new byte[2]; + startOffset = 0; + numBits = 16; + BitBufferHelper.insertBits(data1, inputdata, startOffset, numBits); + Assert.assertTrue(data1[0] == 75); + Assert.assertTrue(data1[1] == 110); + + byte data2[] = new byte[4]; + startOffset = 0; + numBits = 32; + BitBufferHelper.insertBits(data2, inputdata, startOffset, numBits); + Assert.assertTrue(data2[0] == 75); + Assert.assertTrue(data2[1] == 110); + Assert.assertTrue(data2[2] == 107); + Assert.assertTrue(data2[3] == 80); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [10100000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] // OUTPUT: [01001011] [01101000] = {75, 104} + byte data10[] = new byte[2]; + startOffset = 0; + numBits = 13; + BitBufferHelper.insertBits(data10, inputdata, startOffset, numBits); + Assert.assertTrue(data10[0] == 75); + Assert.assertTrue(data10[1] == 104); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [10100000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] // OUTPUT: [01001000] = {72} + byte data11[] = new byte[4]; + startOffset = 8; + numBits = 6; + BitBufferHelper.insertBits(data11, inputdata, startOffset, numBits); + Assert.assertTrue(data11[1] == 72); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [10100000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [01001011] [01101110] [01101000] = {75, 110, 105} + byte data12[] = new byte[4]; + startOffset = 0; + numBits = 23; + BitBufferHelper.insertBits(data12, inputdata, startOffset, numBits); + Assert.assertTrue(data12[0] == 75); + Assert.assertTrue(data12[1] == 110); + Assert.assertTrue(data12[2] == 106); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [10100000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [01001011] [01101110] [01100000] = {75, 110, 96} + byte data13[] = new byte[4]; + startOffset = 8; + numBits = 20; + BitBufferHelper.insertBits(data13, inputdata, startOffset, numBits); + Assert.assertTrue(data13[1] == 75); + Assert.assertTrue(data13[2] == 110); + Assert.assertTrue(data13[3] == 96); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [10100000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [01001011] [01101110] [01101011] [10100000]= {75, 110, 107, 80} + byte data14[] = new byte[4]; + startOffset = 0; + numBits = 30; + BitBufferHelper.insertBits(data14, inputdata, startOffset, numBits); + Assert.assertTrue(data14[0] == 75); + Assert.assertTrue(data14[1] == 110); + Assert.assertTrue(data14[2] == 107); + Assert.assertTrue(data14[3] == 80); + + //CASE 3: startOffset%8 != 0, numBits%8 = 0 + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [10100000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00001001] [11000000] = {72, 96} + byte data16[] = new byte[5]; + startOffset = 3; + numBits = 8; + BitBufferHelper.insertBits(data16, inputdata, startOffset, numBits); + Assert.assertTrue(data16[0] == 9); + Assert.assertTrue(data16[1] == 96); + Assert.assertTrue(data16[2] == 0); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [00000100] [1011 0110] [1110 0000] = {4, -54, -96} + + startOffset = 3; + numBits = 16; + byte data17[] = new byte[5]; + BitBufferHelper.insertBits(data17, inputdata, startOffset, numBits); + Assert.assertTrue(data17[0] == 9); + Assert.assertTrue(data17[1] == 109); + Assert.assertTrue(data17[2] == -64); + Assert.assertTrue(data17[3] == 0); + + // INPUT: {79, 110, 111} + // = [01001111] [01101110] [01101111] + //OUTPUT: [0000 1001] [1110 1101] [110 00000] = {9, -19, -64} + byte data18[] = new byte[5]; + byte inputdata3[] = { 79, 110, 111 }; + startOffset = 3; + numBits = 16; + BitBufferHelper.insertBits(data18, inputdata3, startOffset, numBits); + Assert.assertTrue(data18[0] == 9); + Assert.assertTrue(data18[1] == -19); + Assert.assertTrue(data18[2] == -64); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [0000 1001] [0110 1101] [1100 1101] [0110 1010] [0000 0001] = {9, 109, -51, 106, 0} + + startOffset = 3; + numBits = 32; + byte data19[] = new byte[5]; + BitBufferHelper.insertBits(data19, inputdata, startOffset, numBits); + Assert.assertTrue(data19[0] == 9); + Assert.assertTrue(data19[1] == 109); + Assert.assertTrue(data19[2] == -51); + Assert.assertTrue(data19[3] == 106); + Assert.assertTrue(data19[4] == 0); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: data[4, 5, 6] = [0 010 0101] [1 011 0111] [0 000 0000] = {37, -73, 0} + startOffset = 33; + numBits = 16; + byte data20[] = new byte[7]; + BitBufferHelper.insertBits(data20, inputdata, startOffset, numBits); + Assert.assertTrue(data20[4] == 37); + Assert.assertTrue(data20[5] == -73); + Assert.assertTrue(data20[6] == 0); + + //CASE 4: extranumBits != 0 AND extraOffsetBits != 0 + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [0000 1001] [0100 0000] = {9, 96} + startOffset = 3; + numBits = 7; + byte data21[] = new byte[7]; + BitBufferHelper.insertBits(data21, inputdata, startOffset, numBits); + Assert.assertTrue(data21[0] == 9); + Assert.assertTrue(data21[1] == 64); + Assert.assertTrue(data21[2] == 0); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: data = [00000 010] [01011 011] [01110 000] = {37, -73, 0} + startOffset = 5; + numBits = 17; + byte data22[] = new byte[7]; + BitBufferHelper.insertBits(data22, inputdata, startOffset, numBits); + Assert.assertTrue(data22[0] == 2); + Assert.assertTrue(data22[1] == 91); + Assert.assertTrue(data22[2] == 112); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [0000 1001] [0110 1101] [110 01101] [01 00000] = {9, 109, -51, 64} + startOffset = 3; + numBits = 23; + byte data23[] = new byte[7]; + BitBufferHelper.insertBits(data23, inputdata, startOffset, numBits); + Assert.assertTrue(data23[0] == 9); + Assert.assertTrue(data23[1] == 109); + Assert.assertTrue(data23[2] == -51); + Assert.assertTrue(data23[3] == 64); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [0000 1001] [0110 1101] = {9, 109} + startOffset = 3; + numBits = 13; + byte data24[] = new byte[7]; + BitBufferHelper.insertBits(data24, inputdata, startOffset, numBits); + Assert.assertTrue(data24[0] == 9); + Assert.assertTrue(data24[1] == 109); + Assert.assertTrue(data24[2] == 0); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [0000 0100] [1011 0110] [1110 0110] = {4, -74, -26} + startOffset = 4; + numBits = 20; + byte data25[] = new byte[7]; + BitBufferHelper.insertBits(data25, inputdata, startOffset, numBits); + Assert.assertTrue(data25[0] == 4); + Assert.assertTrue(data25[1] == -74); + Assert.assertTrue(data25[2] == -26); + Assert.assertTrue(data25[3] == -0); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [0000 0010] [0101 1011] = {0, 2, 91, 0} + startOffset = 13; + numBits = 11; + byte data26[] = new byte[7]; + BitBufferHelper.insertBits(data26, inputdata, startOffset, numBits); + Assert.assertTrue(data26[0] == 0); + Assert.assertTrue(data26[1] == 2); + Assert.assertTrue(data26[2] == 91); + Assert.assertTrue(data26[3] == 0); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [000 01001] [011 01101] [110 0 0000] = {9, 109, -64, 0} + startOffset = 3; + numBits = 17; + byte data27[] = new byte[7]; + BitBufferHelper.insertBits(data27, inputdata, startOffset, numBits); + Assert.assertTrue(data27[0] == 9); + Assert.assertTrue(data27[1] == 109); + Assert.assertTrue(data27[2] == -64); + Assert.assertTrue(data27[3] == 0); + + // INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} = + // [01001011] [01101110] [01101011] [01010000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001] //OUTPUT: [00000000] [00000100] [10110110] [11100000]= {0, 4, -54, -96} + // OUTPUT: [00 000000] [00 000000] [00 010010] [11 011011] [10 011010] [11 010100] [0000 0000] = {0, 0, 18, -37,-102,-44,0} + startOffset = 18; + numBits = 34; + byte data28[] = new byte[7]; + BitBufferHelper.insertBits(data28, inputdata, startOffset, numBits); + Assert.assertTrue(data28[0] == 0); + Assert.assertTrue(data28[1] == 0); + Assert.assertTrue(data28[2] == 18); + Assert.assertTrue(data28[3] == -37); + Assert.assertTrue(data28[4] == -102); + Assert.assertTrue(data28[5] == -44); + Assert.assertTrue(data28[6] == 0); + + } + + @Test + public void testGetShort() throws Exception { + byte data[] = new byte[2]; + data[0] = 7; + data[1] = 8; + int length = 9; // num bits + Assert.assertTrue(BitBufferHelper.getShort(data, length) == 264); + + data[0] = 6; + data[1] = 8; + short result = BitBufferHelper.getShort(data, length); + Assert.assertTrue(result == 8); + + data[0] = 8; + data[1] = 47; + result = BitBufferHelper.getShort(data, length); + Assert.assertTrue(result == 47); + + //[0000 0001] [0001 0100] [0110 0100] + byte[] data1 = new byte[2]; + data1[0] = 1; + data1[1] = 20; //data1[2] = 100; + length = 15; + result = BitBufferHelper.getShort(data1, length); + Assert.assertTrue(result == 276); + + byte[] data2 = new byte[2]; + data2[0] = 64; + data2[1] = 99; //data2[2] = 100; + length = 13; + result = BitBufferHelper.getShort(data2, length); + Assert.assertTrue(result == 99); + + byte[] data3 = { 100, 50 }; + result = BitBufferHelper.getShort(data3); + Assert.assertTrue(result == 25650); + } + + @Test + public void testToIntVarLength() throws Exception { + byte data[] = { (byte) 255, (byte) 128 }; + int length = 9; // num bits + Assert.assertTrue(BitBufferHelper.getInt(data, length) == 384); + + byte data2[] = { 0, 8 }; + Assert.assertTrue(BitBufferHelper.getInt(data2, 9) == 8); + + byte data3[] = { 1, 1, 1 }; + Assert.assertTrue(BitBufferHelper.getInt(data3) == 65793); + + byte data4[] = { 1, 1, 1 }; + Assert.assertTrue(BitBufferHelper.getInt(data4) == 65793); + + byte data5[] = { 1, 1 }; + Assert.assertTrue(BitBufferHelper.getInt(data5) == 257); + + } + + @Test + public void testShiftBitstoLSB() { + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + + byte[] data2 = { 8, 9, 10 }; + byte[] shiftedBytes2 = BitBufferHelper.shiftBitsToLSB(data2, 11); + + Assert.assertTrue(shiftedBytes2[0] == 0); + Assert.assertTrue(shiftedBytes2[1] == 64); + Assert.assertTrue(shiftedBytes2[2] == 72); + + byte[] shiftedBytes = BitBufferHelper.shiftBitsToLSB(data, 49); + + Assert.assertTrue(shiftedBytes[0] == 0); + Assert.assertTrue(shiftedBytes[1] == 2); + Assert.assertTrue(shiftedBytes[2] == 4); + Assert.assertTrue(shiftedBytes[3] == 6); + Assert.assertTrue(shiftedBytes[4] == 8); + Assert.assertTrue(shiftedBytes[5] == 10); + Assert.assertTrue(shiftedBytes[6] == 12); + Assert.assertTrue(shiftedBytes[7] == 14); + Assert.assertTrue(shiftedBytes[8] == 16); + Assert.assertTrue(shiftedBytes[9] == 18); + + byte[] data1 = { 1, 2, 3 }; + byte[] shiftedBytes1 = BitBufferHelper.shiftBitsToLSB(data1, 18); + Assert.assertTrue(shiftedBytes1[0] == 0); + Assert.assertTrue(shiftedBytes1[1] == 4); + Assert.assertTrue(shiftedBytes1[2] == 8); + + } + + @Test + public void testShiftBitstoLSBMSB() { + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + byte[] clone = BitBufferHelper.shiftBitsToMSB(BitBufferHelper + .shiftBitsToLSB(data, 72), 72); + + Assert.assertTrue(clone[0] == 1); + Assert.assertTrue(clone[1] == 2); + Assert.assertTrue(clone[2] == 3); + Assert.assertTrue(clone[3] == 4); + Assert.assertTrue(clone[4] == 5); + Assert.assertTrue(clone[5] == 6); + Assert.assertTrue(clone[6] == 7); + Assert.assertTrue(clone[7] == 8); + Assert.assertTrue(clone[8] == 9); + Assert.assertTrue(clone[9] == 0); + } + +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/EthernetTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/EthernetTest.java new file mode 100644 index 0000000000..61d5baa57d --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/EthernetTest.java @@ -0,0 +1,99 @@ + +/* + * 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.controller.sal.packet; + +import junit.framework.Assert; + +import org.junit.Test; +import org.opendaylight.controller.sal.packet.Ethernet; + +public class EthernetTest { + + @Test + public void testGetDestinationMACAddress() { + Ethernet eth = new Ethernet(); + byte mac[] = { 10, 12, 14, 20, 55, 69 }; + eth.hdrFieldsMap.put("DestinationMACAddress", mac); + byte[] dMAC = eth.getDestinationMACAddress(); + Assert.assertTrue(dMAC[0] == 10); + Assert.assertTrue(dMAC[1] == 12); + Assert.assertTrue(dMAC[2] == 14); + Assert.assertTrue(dMAC[3] == 20); + Assert.assertTrue(dMAC[4] == 55); + Assert.assertTrue(dMAC[5] == 69); + + } + + @Test + public void testSourceMACAddress() { + Ethernet eth = new Ethernet(); + byte mac[] = { 120, 30, 25, 80, 66, 99 }; + eth.hdrFieldsMap.put("SourceMACAddress", mac); + byte[] sMAC = eth.getSourceMACAddress(); + Assert.assertTrue(sMAC[0] == 120); + Assert.assertTrue(sMAC[1] == 30); + Assert.assertTrue(sMAC[2] == 25); + Assert.assertTrue(sMAC[3] == 80); + Assert.assertTrue(sMAC[4] == 66); + Assert.assertTrue(sMAC[5] == 99); + + } + + @Test + public void testGetEthertype() throws Exception { + Ethernet eth = new Ethernet(); + byte ethType[] = { 8, 6 }; + eth.hdrFieldsMap.put("EtherType", ethType); + short etherType = eth.getEtherType(); + Assert.assertTrue(etherType == 2054); + } + + @Test + public void testSetDestinationMACAddress() { + Ethernet eth = new Ethernet(); + byte mac[] = { 10, 12, 14, 20, 55, 69 }; + eth.setDestinationMACAddress(mac); + byte[] dMAC = eth.hdrFieldsMap.get("DestinationMACAddress"); + Assert.assertTrue(dMAC[0] == 10); + Assert.assertTrue(dMAC[1] == 12); + Assert.assertTrue(dMAC[2] == 14); + Assert.assertTrue(dMAC[3] == 20); + Assert.assertTrue(dMAC[4] == 55); + Assert.assertTrue(dMAC[5] == 69); + + } + + @Test + public void testSetSourceMACAddress() { + Ethernet eth = new Ethernet(); + byte mac[] = { 120, 30, 25, 80, 66, 99 }; + eth.setSourceMACAddress(mac); + byte[] sMAC = eth.hdrFieldsMap.get("SourceMACAddress"); + Assert.assertTrue(sMAC[0] == 120); + Assert.assertTrue(sMAC[1] == 30); + Assert.assertTrue(sMAC[2] == 25); + Assert.assertTrue(sMAC[3] == 80); + Assert.assertTrue(sMAC[4] == 66); + Assert.assertTrue(sMAC[5] == 99); + + } + + @Test + public void testSetEthertype() throws Exception { + Ethernet eth = new Ethernet(); + short ethType = 2054; + eth.setEtherType(ethType); + byte[] etherType = eth.hdrFieldsMap.get("EtherType"); + Assert.assertTrue(etherType[0] == 8); + Assert.assertTrue(etherType[1] == 6); + + } + +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ICMPTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ICMPTest.java new file mode 100644 index 0000000000..445f7211c0 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ICMPTest.java @@ -0,0 +1,62 @@ + +/* + * 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.controller.sal.packet; + +import junit.framework.Assert; + +import org.junit.Test; +import org.opendaylight.controller.sal.packet.ICMP; + +public class ICMPTest { + + @Test + public void testSetTypeCode() { + ICMP icmp = new ICMP(); + short icmpTypeCode = 2; + icmp.setTypeCode(icmpTypeCode); + byte[] typeCode = icmp.hdrFieldsMap.get("TypeCode"); + Assert.assertTrue(typeCode[0] == 0); + Assert.assertTrue(typeCode[1] == 2); + + } + + @Test + public void testSetChecksum() { + ICMP icmp = new ICMP(); + short icmpChecksum = 200; + icmp.setChecksum(icmpChecksum); + byte[] checksum = icmp.hdrFieldsMap.get("HeaderChecksum"); + Assert.assertTrue(checksum[0] == 0); + Assert.assertTrue(checksum[1] == -56); + + } + + @Test + public void testSetIdentifier() { + ICMP icmp = new ICMP(); + short icmpIdentifier = 1201; + icmp.setIdentifier(icmpIdentifier); + byte[] identifier = icmp.hdrFieldsMap.get("Identifier"); + Assert.assertTrue(identifier[0] == 4); + Assert.assertTrue(identifier[1] == -79); + + } + + @Test + public void testSetSequenceNumber() { + ICMP icmp = new ICMP(); + short icmpSequenceNumber = 5000; + icmp.setSequenceNumber(icmpSequenceNumber); + byte[] sequenceNumber = icmp.hdrFieldsMap.get("SequenceNumber"); + Assert.assertTrue(sequenceNumber[0] == 19); + Assert.assertTrue(sequenceNumber[1] == -120); + + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IPv4Test.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IPv4Test.java new file mode 100644 index 0000000000..beeb7d13c0 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IPv4Test.java @@ -0,0 +1,222 @@ + +/* + * 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.controller.sal.packet; + +import junit.framework.Assert; + +import org.junit.Test; +import org.opendaylight.controller.sal.packet.ICMP; +import org.opendaylight.controller.sal.packet.IPv4; +import org.opendaylight.controller.sal.packet.Packet; + +public class IPv4Test { + + @Test + public void testGetVersion() { + IPv4 ip = new IPv4(); + byte[] ipVersion = { (byte) 4 }; + ip.hdrFieldsMap.put("Version", ipVersion); + byte version = ip.getVersion(); + Assert.assertTrue(version == (byte) 4); + } + + @Test + public void testGetHeaderLength() { + IPv4 ip = new IPv4(); + byte[] ipHeaderLength = { 5 }; + ip.hdrFieldsMap.put("HeaderLength", ipHeaderLength); + byte headerLength = (byte) ip.getHeaderLen(); + Assert.assertTrue(headerLength == 20); + } + + @Test + public void testGetDiffServ() { + IPv4 ip = new IPv4(); + byte[] ipDiffServ = { 20 }; + ip.hdrFieldsMap.put("DiffServ", ipDiffServ); + byte diffServ = ip.getDiffServ(); + Assert.assertTrue(diffServ == 20); + } + + @Test + public void testGetTotalLength() { + IPv4 ip = new IPv4(); + byte[] iptotLength = { 3, -24 }; + ip.hdrFieldsMap.put("TotalLength", iptotLength); + short totalLength = ip.getTotalLength(); + //System.out.println(totalLength); + Assert.assertTrue(totalLength == 1000); + } + + @Test + public void testGetIdentification() { + IPv4 ip = new IPv4(); + byte[] ipIdentification = { 7, -48 }; + ip.hdrFieldsMap.put("Identification", ipIdentification); + short identification = ip.getIdentification(); + Assert.assertTrue(identification == 2000); + } + + @Test + public void testGetFlags() { + IPv4 ip = new IPv4(); + byte[] ipFlags = { 7 }; + ip.hdrFieldsMap.put("Flags", ipFlags); + byte flags = ip.getFlags(); + Assert.assertTrue(flags == 7); + } + + @Test + public void testGetTtl() { + IPv4 ip = new IPv4(); + byte[] ipTtl = { 100 }; + ip.hdrFieldsMap.put("TTL", ipTtl); + byte ttl = ip.getTtl(); + Assert.assertTrue(ttl == 100); + } + + @Test + public void testGetProtocol() { + IPv4 ip = new IPv4(); + byte[] ipProtocol = { 1 }; + ip.hdrFieldsMap.put("Protocol", ipProtocol); + byte protocol = ip.getProtocol(); + Assert.assertTrue(protocol == 1); + + Class clazz = ip.protocolClassMap.get(protocol); + System.out.printf("clazz = %s\n", clazz.getName()); + Assert.assertTrue(clazz == ICMP.class); + } + + @Test + public void testGetFragmentOffset() { + IPv4 ip = new IPv4(); + byte[] ipFragmentOffset = { 6, -35 }; + ip.hdrFieldsMap.put("FragmentOffset", ipFragmentOffset); + short fragmentOffset = ip.getFragmentOffset(); + Assert.assertTrue(fragmentOffset == 1757); + } + + @Test + public void testGetSourceAddress() { + IPv4 ip = new IPv4(); + byte[] ipSourceAddress = { 10, 110, 31, 55 }; + ip.hdrFieldsMap.put("SourceIPAddress", ipSourceAddress); + int sourceAddress = ip.getSourceAddress(); + Assert.assertTrue(sourceAddress == 174989111); + } + + @Test + public void testGetDestinationAddress() { + IPv4 ip = new IPv4(); + byte[] ipDestinationAddress = { 20, 55, 62, 110 }; + ip.hdrFieldsMap.put("DestinationIPAddress", ipDestinationAddress); + int destinationAddress = ip.getDestinationAddress(); + Assert.assertTrue(destinationAddress == 339164782); + } + + @Test + public void testSetVersion() { + IPv4 ip = new IPv4(); + byte ipVersion = (byte) 4; + ip.setVersion(ipVersion); + byte[] version = ip.hdrFieldsMap.get("Version"); + Assert.assertTrue(version[0] == (byte) 4); + } + + @Test + public void testSetHeaderLength() { + IPv4 ip = new IPv4(); + byte ipHeaderLength = 5; + ip.setHeaderLength(ipHeaderLength); + byte[] headerLength = ip.hdrFieldsMap.get("HeaderLength"); + Assert.assertTrue(headerLength[0] == 5); + } + + @Test + public void testSetDiffServ() { + IPv4 ip = new IPv4(); + byte ipDiffServ = 20; + ip.setDiffServ(ipDiffServ); + byte[] diffServ = ip.hdrFieldsMap.get("DiffServ"); + Assert.assertTrue(diffServ[0] == 20); + } + + @Test + public void testSetTotalLength() { + IPv4 ip = new IPv4(); + short iptotLength = 1000; + ip.setTotalLength(iptotLength); + byte[] totalLength = ip.hdrFieldsMap.get("TotalLength"); + Assert.assertTrue(totalLength[0] == 3); + Assert.assertTrue(totalLength[1] == -24); + } + + @Test + public void testSetIdentification() { + IPv4 ip = new IPv4(); + short ipIdentification = 2000; + ip.setIdentification(ipIdentification); + byte[] identification = ip.hdrFieldsMap.get("Identification"); + Assert.assertTrue(identification[0] == 7); + Assert.assertTrue(identification[1] == -48); + } + + @Test + public void testSetFlags() { + IPv4 ip = new IPv4(); + byte ipFlags = 7; + ip.setFlags(ipFlags); + byte[] flags = ip.hdrFieldsMap.get("Flags"); + Assert.assertTrue(flags[0] == 7); + } + + @Test + public void testSetTtl() { + IPv4 ip = new IPv4(); + byte ipTtl = 100; + ip.setTtl(ipTtl); + byte[] ttl = ip.hdrFieldsMap.get("TTL"); + Assert.assertTrue(ttl[0] == 100); + } + + @Test + public void testSetProtocol() { + IPv4 ip = new IPv4(); + byte ipProtocol = 11; + ip.setProtocol(ipProtocol); + byte[] protocol = ip.hdrFieldsMap.get("Protocol"); + Assert.assertTrue(protocol[0] == 11); + } + + @Test + public void testSetFragmentOffset() { + IPv4 ip = new IPv4(); + short ipFragmentOffset = 1757; + ip.setFragmentOffset(ipFragmentOffset); + byte[] fragmentOffset = ip.hdrFieldsMap.get("FragmentOffset"); + Assert.assertTrue(fragmentOffset[0] == 6); + Assert.assertTrue(fragmentOffset[1] == -35); + } + + + @Test + public void testSetDestinationAddress() { + IPv4 ip = new IPv4(); + int ipDestinationAddress = 339164782; + ip.setDestinationAddress(ipDestinationAddress); + byte[] destinationAddress = ip.hdrFieldsMap.get("DestinationIPAddress"); + Assert.assertTrue(destinationAddress[0] == 20); + Assert.assertTrue(destinationAddress[1] == 55); + Assert.assertTrue(destinationAddress[2] == 62); + Assert.assertTrue(destinationAddress[3] == 110); + } + +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/PacketTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/PacketTest.java new file mode 100644 index 0000000000..8d856b08cd --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/PacketTest.java @@ -0,0 +1,164 @@ + +/* + * 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.controller.sal.packet; + +import java.util.Map; + +import junit.framework.Assert; + +import org.junit.Test; +import org.opendaylight.controller.sal.packet.Ethernet; + +public class PacketTest { + + @Test + public void testDeserialize() throws NoSuchFieldException, Exception { + short startOffset, numBits; + + Ethernet eth = new Ethernet(); + byte[] data = { 10, 12, 14, 20, 55, 69, //DMAC + -90, -20, -100, -82, -78, -97, //SMAC + 8, 6, //ethype + 0, 1, // hw type + 8, 0, // proto (ip) + 6, // hw addr len + 4, // proto addr len + 0, 1, // op codes + -90, -20, -100, -82, -78, -97, //src hw addr + 9, 9, 9, 1, // src proto + 0, 0, 0, 0, 0, 0, // target hw addr + 9, 9, 9, -2 }; // target proto + + startOffset = 0; + numBits = 42 * 8; + eth.deserialize(data, startOffset, numBits); + + byte[] dMAC = eth.getDestinationMACAddress(); + byte[] sMAC = eth.getSourceMACAddress(); + short etherType = eth.getEtherType(); + + Assert.assertTrue(dMAC[0] == 10); + Assert.assertTrue(dMAC[1] == 12); + Assert.assertTrue(dMAC[2] == 14); + Assert.assertTrue(dMAC[3] == 20); + Assert.assertTrue(dMAC[4] == 55); + Assert.assertTrue(dMAC[5] == 69); + + Assert.assertTrue(sMAC[0] == -90); + Assert.assertTrue(sMAC[1] == -20); + Assert.assertTrue(sMAC[2] == -100); + Assert.assertTrue(sMAC[3] == -82); + Assert.assertTrue(sMAC[4] == -78); + Assert.assertTrue(sMAC[5] == -97); + + Assert.assertTrue(etherType == 0x806); + + ARP arpPacket = (ARP) eth.getPayload(); + + Assert.assertTrue(arpPacket.getHardwareType() == (byte)0x1); + Assert.assertTrue(arpPacket.getProtocolType() == 2048); + Assert.assertTrue(arpPacket.getHardwareAddressLength() == (byte)0x6); + Assert.assertTrue(arpPacket.getProtocolAddressLength() == (byte)0x4); + Assert.assertTrue(arpPacket.getOpCode() == 1); + + byte[] senderHwAddress = arpPacket.getSenderHardwareAddress(); + byte[] senderProtocolAddress = arpPacket.getSenderProtocolAddress(); + + byte[] targetHwAddress = arpPacket.getTargetHardwareAddress(); + byte[] targetProtocolAddress = arpPacket.getTargetProtocolAddress(); + + + Assert.assertTrue(senderHwAddress[0] == (byte)0xA6); + Assert.assertTrue(senderHwAddress[1] == (byte)0xEC); + Assert.assertTrue(senderHwAddress[2] == (byte)0x9C); + Assert.assertTrue(senderHwAddress[3] == (byte)0xAE); + Assert.assertTrue(senderHwAddress[4] == (byte)0xB2); + Assert.assertTrue(senderHwAddress[5] == (byte)0x9F); + + Assert.assertTrue(senderProtocolAddress[0] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[1] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[2] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[3] == (byte)0x1); + + Assert.assertTrue(targetHwAddress[0] == (byte)0x0); + Assert.assertTrue(targetHwAddress[1] == (byte)0x0); + Assert.assertTrue(targetHwAddress[2] == (byte)0x0); + Assert.assertTrue(targetHwAddress[3] == (byte)0x0); + Assert.assertTrue(targetHwAddress[4] == (byte)0x0); + Assert.assertTrue(targetHwAddress[5] == (byte)0x0); + + Assert.assertTrue(senderProtocolAddress[0] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[1] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[2] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[3] == (byte)0x1); + + Assert.assertTrue(targetProtocolAddress[0] == (byte)0x9); + Assert.assertTrue(targetProtocolAddress[1] == (byte)0x9); + Assert.assertTrue(targetProtocolAddress[2] == (byte)0x9); + Assert.assertTrue(targetProtocolAddress[3] == (byte)0xFE); + } + + @Test + public void testSerialize() throws NoSuchFieldException, Exception { + Ethernet eth = new Ethernet(); + Map fCValues = eth.hdrFieldsMap; + + byte[] dMAC = { 10, 12, 14, 20, 55, 69 }; + byte[] sMAC = { 82, 97, 109, 117, 127, -50 }; + short etherType = 2054; + + byte[] dMACdata, sMACdata, etherTypedata; + byte[] data = new byte[20]; + + eth.setDestinationMACAddress(dMAC); + eth.setSourceMACAddress(sMAC); + eth.setEtherType(etherType); + + dMACdata = (byte[]) fCValues.get("DestinationMACAddress"); + sMACdata = (byte[]) fCValues.get("SourceMACAddress"); + etherTypedata = (byte[]) fCValues.get("EtherType"); + + Assert.assertTrue(dMACdata[0] == 10); + Assert.assertTrue(dMACdata[1] == 12); + Assert.assertTrue(dMACdata[2] == 14); + Assert.assertTrue(dMACdata[3] == 20); + Assert.assertTrue(dMACdata[4] == 55); + Assert.assertTrue(dMACdata[5] == 69); + + Assert.assertTrue(sMACdata[0] == 82); + Assert.assertTrue(sMACdata[1] == 97); + Assert.assertTrue(sMACdata[2] == 109); + Assert.assertTrue(sMACdata[3] == 117); + Assert.assertTrue(sMACdata[4] == 127); + Assert.assertTrue(sMACdata[5] == -50); + + Assert.assertTrue(etherTypedata[0] == 8); + Assert.assertTrue(etherTypedata[1] == 6); + data = eth.serialize(); + + Assert.assertTrue(data[0] == 10); + Assert.assertTrue(data[1] == 12); + Assert.assertTrue(data[2] == 14); + Assert.assertTrue(data[3] == 20); + Assert.assertTrue(data[4] == 55); + Assert.assertTrue(data[5] == 69); + + Assert.assertTrue(data[6] == 82); + Assert.assertTrue(data[7] == 97); + Assert.assertTrue(data[8] == 109); + Assert.assertTrue(data[9] == 117); + Assert.assertTrue(data[10] == 127); + Assert.assertTrue(data[11] == -50); + + Assert.assertTrue(data[12] == 8); + Assert.assertTrue(data[13] == 6); + + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/TCPTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/TCPTest.java new file mode 100644 index 0000000000..90f963c122 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/TCPTest.java @@ -0,0 +1,108 @@ + +/* + * 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.controller.sal.packet; + +import junit.framework.Assert; + +import org.junit.Test; +import org.opendaylight.controller.sal.packet.TCP; + +public class TCPTest { + + @Test + public void testSetSourcePort() { + TCP tcp = new TCP(); + short tcpSourcePort = 118; + tcp.setSourcePort(tcpSourcePort); + byte[] sourcePort = tcp.hdrFieldsMap.get("SourcePort"); + Assert.assertTrue(sourcePort[0] == 0); + Assert.assertTrue(sourcePort[1] == 118); + + } + + @Test + public void testSetDestinationPort() { + TCP tcp = new TCP(); + short tcpDestinationPort = 443; + tcp.setDestinationPort(tcpDestinationPort); + byte[] destinationPort = tcp.hdrFieldsMap.get("DestinationPort"); + Assert.assertTrue(destinationPort[0] == 1); + Assert.assertTrue(destinationPort[1] == -69); + + } + + @Test + public void testSetSequenceNumber() { + TCP tcp = new TCP(); + short tcpSequenceNumber = 700; + tcp.setSequenceNumber(tcpSequenceNumber); + byte[] sequenceNumber = tcp.hdrFieldsMap.get("SequenceNumber"); + Assert.assertTrue(sequenceNumber[0] == 0); + Assert.assertTrue(sequenceNumber[1] == 0); + Assert.assertTrue(sequenceNumber[2] == 2); + Assert.assertTrue(sequenceNumber[3] == -68); + } + + @Test + public void testSetAckNumber() { + TCP tcp = new TCP(); + short tcpAckNumber = 697; + tcp.setAckNumber(tcpAckNumber); + byte[] ackNumber = tcp.hdrFieldsMap.get("AcknoledgementNumber"); + Assert.assertTrue(ackNumber[0] == 0); + Assert.assertTrue(ackNumber[1] == 0); + Assert.assertTrue(ackNumber[2] == 2); + Assert.assertTrue(ackNumber[3] == -71); + } + + @Test + public void testSetHeaderLenFlags() { + TCP tcp = new TCP(); + short tcpFlags = 26; + tcp.setHeaderLenFlags(tcpFlags); + byte[] headerLenFlags = tcp.hdrFieldsMap.get("HeaderLenFlags"); + Assert.assertTrue(headerLenFlags[0] == 0); + Assert.assertTrue(headerLenFlags[1] == 26); + + } + + @Test + public void testSetWindowSize() { + TCP tcp = new TCP(); + short tcpWindowSize = 100; + tcp.setWindowSize(tcpWindowSize); + byte[] windowSize = tcp.hdrFieldsMap.get("WindowSize"); + Assert.assertTrue(windowSize[0] == 0); + Assert.assertTrue(windowSize[1] == 100); + + } + + @Test + public void testSetChecksum() { + TCP tcp = new TCP(); + short tcpChecksum = 134; + tcp.setChecksum(tcpChecksum); + byte[] checksum = tcp.hdrFieldsMap.get("Checksum"); + Assert.assertTrue(checksum[0] == 0); + Assert.assertTrue(checksum[1] == -122); + + } + + @Test + public void testSetUrgentPointer() { + TCP tcp = new TCP(); + short tcpUrgentPointer = 25098; + tcp.setUrgentPointer(tcpUrgentPointer); + byte[] urgentPointer = tcp.hdrFieldsMap.get("UrgentPointer"); + Assert.assertTrue(urgentPointer[0] == 98); + Assert.assertTrue(urgentPointer[1] == 10); + + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/UDPTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/UDPTest.java new file mode 100644 index 0000000000..26d4980ad3 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/UDPTest.java @@ -0,0 +1,99 @@ + +/* + * 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.controller.sal.packet; + +import junit.framework.Assert; + +import org.junit.Test; +import org.opendaylight.controller.sal.packet.UDP; + +public class UDPTest { + + @Test + public void testGetSourcePort() { + UDP udp = new UDP(); + byte[] udpSourcePort = { 0, 118 }; + udp.hdrFieldsMap.put("SourcePort", udpSourcePort); + short sourcePort = udp.getSourcePort(); + Assert.assertTrue(sourcePort == 118); + } + + @Test + public void testGetDestinationPort() { + UDP udp = new UDP(); + byte[] udpDestinationPort = { 1, -69 }; + udp.hdrFieldsMap.put("DestinationPort", udpDestinationPort); + short destinationPort = udp.getDestinationPort(); + Assert.assertTrue(destinationPort == 443); + } + + @Test + public void testGetLength() { + UDP udp = new UDP(); + byte[] udpLength = { 0, 20 }; + udp.hdrFieldsMap.put("Length", udpLength); + short length = udp.getLength(); + Assert.assertTrue(length == 20); + } + + @Test + public void testGetChecksum() { + UDP udp = new UDP(); + byte[] udpChecksum = { 0, -56 }; + udp.hdrFieldsMap.put("Checksum", udpChecksum); + short checksum = udp.getChecksum(); + Assert.assertTrue(checksum == 200); + } + + @Test + public void testSetSourcePort() { + UDP udp = new UDP(); + short tcpSourcePort = 118; + udp.setSourcePort(tcpSourcePort); + byte[] sourcePort = udp.hdrFieldsMap.get("SourcePort"); + Assert.assertTrue(sourcePort[0] == 0); + Assert.assertTrue(sourcePort[1] == 118); + + } + + @Test + public void testSetDestinationPort() { + UDP udp = new UDP(); + short tcpDestinationPort = 443; + udp.setDestinationPort(tcpDestinationPort); + byte[] destinationPort = udp.hdrFieldsMap.get("DestinationPort"); + Assert.assertTrue(destinationPort[0] == 1); + Assert.assertTrue(destinationPort[1] == -69); + + } + + @Test + public void testSetLength() { + UDP udp = new UDP(); + short udpLength = 20; + udp.setLength(udpLength); + byte[] length = udp.hdrFieldsMap.get("Length"); + Assert.assertTrue(length[0] == 0); + Assert.assertTrue(length[1] == 20); + + } + + @Test + public void testSetChecksum() { + UDP udp = new UDP(); + short udpChecksum = 200; + udp.setChecksum(udpChecksum); + byte[] checksum = udp.hdrFieldsMap.get("Checksum"); + Assert.assertTrue(checksum[0] == 0); + Assert.assertTrue(checksum[1] == -56); + + } + +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/address/EthernetAddressTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/address/EthernetAddressTest.java new file mode 100644 index 0000000000..235a754947 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/address/EthernetAddressTest.java @@ -0,0 +1,113 @@ + +/* + * 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 + */ + +/** + * @file EthernetAddressTest.java + * + * @brief Unit Tests for EthernetAddress class + * + * Unit Tests for EthernetAddress class + */ +package org.opendaylight.controller.sal.packet.address; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.packet.address.EthernetAddress; + +public class EthernetAddressTest { + @Test + public void testNonValidConstructor() { + EthernetAddress ea1; + // Null input array + try { + ea1 = new EthernetAddress((byte[]) null); + + // Exception is expected if NOT raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + // Array too short + try { + ea1 = new EthernetAddress(new byte[] { (byte) 0x0, (byte) 0x0 }); + + // Exception is expected if NOT raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + + // Array too long + try { + ea1 = new EthernetAddress(new byte[] { (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0 }); + + // Exception is expected if NOT raised test will fail + Assert.assertTrue(false); + } catch (ConstructionException e) { + } + } + + @Test + public void testEquality() { + EthernetAddress ea1; + EthernetAddress ea2; + try { + ea1 = new EthernetAddress(new byte[] { (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1 }); + + ea2 = new EthernetAddress(new byte[] { (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1 }); + Assert.assertTrue(ea1.equals(ea2)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + try { + ea1 = new EthernetAddress(new byte[] { (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1 }); + + ea2 = ea1.clone(); + Assert.assertTrue(ea1.equals(ea2)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + + // Check for well knowns + try { + ea1 = EthernetAddress.BROADCASTMAC; + ea2 = new EthernetAddress(new byte[] { (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }); + Assert.assertTrue(ea1.equals(ea2)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + } + + @Test + public void testUnEquality() { + EthernetAddress ea1; + EthernetAddress ea2; + try { + ea1 = new EthernetAddress(new byte[] { (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2 }); + + ea2 = new EthernetAddress(new byte[] { (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1 }); + Assert.assertTrue(!ea1.equals(ea2)); + } catch (ConstructionException e) { + // Exception is NOT expected if raised test will fail + Assert.assertTrue(false); + } + } +} diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/FlowOnNodeTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/FlowOnNodeTest.java new file mode 100644 index 0000000000..61f34aa63a --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/FlowOnNodeTest.java @@ -0,0 +1,59 @@ + +/* + * 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.controller.sal.reader; + +import java.util.ArrayList; +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.action.Action; +import org.opendaylight.controller.sal.action.Output; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.flowprogrammer.Flow; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; +import org.opendaylight.controller.sal.reader.FlowOnNode; +import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.opendaylight.controller.sal.utils.NodeCreator; + +public class FlowOnNodeTest { + + @Test + public void testFlowOnNodeMethods () { + Match match = new Match(); + NodeConnector inNC = NodeConnectorCreator.createNodeConnector((short)10, NodeCreator.createOFNode((long)10)); + NodeConnector outNC = NodeConnectorCreator.createNodeConnector((short)20, NodeCreator.createOFNode((long)20)); + + match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()); + match.setField(MatchType.IN_PORT, inNC); + + Output output = new Output(outNC); + ArrayList action = new ArrayList(); + action.add(output); + + Flow flow = new Flow (match, action); + + FlowOnNode flowOnNode = new FlowOnNode (flow); + + Assert.assertTrue(flowOnNode.getFlow().equals(flow)); + + flowOnNode.setPacketCount((long)100); + flowOnNode.setByteCount((long)800); + flowOnNode.setTableId((byte)0x55); + flowOnNode.setDurationNanoseconds(40); + flowOnNode.setDurationSeconds(45); + + Assert.assertTrue(flowOnNode.getPacketCount() == 100); + Assert.assertTrue(flowOnNode.getByteCount() == 800); + Assert.assertTrue(flowOnNode.getDurationNanoseconds() == 40); + Assert.assertTrue(flowOnNode.getDurationSeconds() == 45); + Assert.assertTrue(flowOnNode.getTableId() == (byte)0x55); + } +} \ No newline at end of file diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeConnectorStatisticsTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeConnectorStatisticsTest.java new file mode 100644 index 0000000000..8c2d2e6e34 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeConnectorStatisticsTest.java @@ -0,0 +1,52 @@ + +/* + * 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.controller.sal.reader; + +import org.junit.Test; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.reader.NodeConnectorStatistics; +import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.opendaylight.controller.sal.utils.NodeCreator; +import org.junit.Assert; + +public class NodeConnectorStatisticsTest { + + @Test + public void testNodeConnectorStatisticsMethods() { + NodeConnector nc = NodeConnectorCreator.createNodeConnector((short)20, NodeCreator.createOFNode((long)20)); + NodeConnectorStatistics ncStats = new NodeConnectorStatistics(); + ncStats.setNodeConnector(nc); + ncStats.setReceiveByteCount(800); + ncStats.setReceiveCRCErrorCount(10); + ncStats.setReceiveDropCount(5); + ncStats.setReceiveErrorCount(20); + ncStats.setReceiveFrameErrorCount(25); + ncStats.setReceiveOverRunErrorCount(30); + ncStats.setReceivePacketCount(100); + ncStats.setTransmitByteCount(400); + ncStats.setTransmitDropCount(15); + ncStats.setTransmitErrorCount(18); + ncStats.setTransmitPacketCount(50); + ncStats.setCollisionCount(2); + + Assert.assertTrue(ncStats.getCollisionCount() == 2); + Assert.assertTrue(ncStats.getTransmitPacketCount() == 50); + Assert.assertTrue(ncStats.getTransmitErrorCount() == 18); + Assert.assertTrue(ncStats.getTransmitDropCount() == 15); + Assert.assertTrue(ncStats.getReceivePacketCount() == 100); + Assert.assertTrue(ncStats.getReceiveOverRunErrorCount() == 30); + Assert.assertTrue(ncStats.getReceiveFrameErrorCount() == 25); + Assert.assertTrue(ncStats.getReceiveDropCount() == 5); + Assert.assertTrue(ncStats.getReceiveCRCErrorCount() == 10); + Assert.assertTrue(ncStats.getReceiveByteCount() == 800); + Assert.assertTrue(ncStats.getNodeConnector().equals(nc)); + } +} + diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeDescriptionTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeDescriptionTest.java new file mode 100644 index 0000000000..a78182ff09 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/reader/NodeDescriptionTest.java @@ -0,0 +1,43 @@ + +/* + * 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.controller.sal.reader; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.reader.NodeDescription; + +public class NodeDescriptionTest { + + @Test + public void testNodeDescriptionMethods() { + NodeDescription ncDesc = new NodeDescription(); + ncDesc.setHardware("Hardware1"); + ncDesc.setManufacturer("Manufacturer1"); + ncDesc.setSdnProtocolDescription("SDNProtocol1"); + ncDesc.setSerialNumber("serialNumber1"); + ncDesc.setSoftware("Software1"); + + Assert.assertTrue(ncDesc.getHardware().equals("Hardware1")); + Assert.assertTrue(ncDesc.getManufacturer().equals("Manufacturer1")); + Assert.assertTrue(ncDesc.getSdnProtocolDescription().equals("SDNProtocol1")); + Assert.assertTrue(ncDesc.getSerialNumber().equals("serialNumber1")); + Assert.assertTrue(ncDesc.getSoftware().equals("Software1")); + + Assert.assertFalse(ncDesc.getHardware().equals("Hardware2")); + Assert.assertFalse(ncDesc.getManufacturer().equals("Manufacturer2")); + Assert.assertFalse(ncDesc.getSdnProtocolDescription().equals("SDNProtocol2")); + Assert.assertFalse(ncDesc.getSerialNumber().equals("serialNumber2")); + Assert.assertFalse(ncDesc.getSoftware().equals("Software2")); + + } +} + + + diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/EtherTypesTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/EtherTypesTest.java new file mode 100644 index 0000000000..117da55de8 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/EtherTypesTest.java @@ -0,0 +1,74 @@ + +/* + * 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.controller.sal.utils; + +import java.util.ArrayList; +import org.junit.Assert; +import org.junit.Test; + +public class EtherTypesTest { + + @Test + public void testEthertypesCreation() { + + EtherTypes arp = EtherTypes.ARP; + + Assert.assertTrue(arp.toString().equals("ARP")); + Assert.assertTrue(arp.intValue() == 2054); + Assert.assertTrue(arp.shortValue() == (short)2054); + } + + @Test + public void testGetEtherTypesString() { + + Assert.assertTrue(EtherTypes.getEtherTypeName(34984).equals("QINQ")); + Assert.assertTrue(EtherTypes.getEtherTypeName((short)2048).equals("IPv4")); + Assert.assertTrue(EtherTypes.getEtherTypeName(0x010B).equals("PVSTP")); + + Assert.assertFalse(EtherTypes.getEtherTypeName(0x800).equals("ARP")); + } + + @Test + public void testGetEtherTypesNumber() { + Assert.assertTrue(EtherTypes.getEtherTypeNumberInt("VLAN Tagged") == 33024); + Assert.assertTrue(EtherTypes.getEtherTypeNumberShort("ARP") == 2054); + + Assert.assertFalse(EtherTypes.getEtherTypeNumberInt("CDP") == 1000); + } + + @Test + public void testGetEtherTypesList() { + ArrayList etherTypeNames = (ArrayList) EtherTypes.getEtherTypesNameList(); + Assert.assertTrue(etherTypeNames.get(0).equals("PVSTP")); + Assert.assertTrue(etherTypeNames.get(1).equals("CDP")); + Assert.assertTrue(etherTypeNames.get(2).equals("VTP")); + Assert.assertTrue(etherTypeNames.get(3).equals("IPv4")); + Assert.assertTrue(etherTypeNames.get(4).equals("ARP")); + Assert.assertTrue(etherTypeNames.get(5).equals("Reverse ARP")); + Assert.assertTrue(etherTypeNames.get(6).equals("VLAN Tagged")); + Assert.assertTrue(etherTypeNames.get(7).equals("IPv6")); + Assert.assertTrue(etherTypeNames.get(8).equals("MPLS Unicast")); + Assert.assertTrue(etherTypeNames.get(9).equals("MPLS Multicast")); + Assert.assertTrue(etherTypeNames.get(10).equals("QINQ")); + Assert.assertTrue(etherTypeNames.get(11).equals("LLDP")); + Assert.assertTrue(etherTypeNames.get(12).equals("Old QINQ")); + Assert.assertTrue(etherTypeNames.get(13).equals("Cisco QINQ")); + } + + @Test + public void testGetEtherTypesloadFromString() { + Assert.assertTrue(EtherTypes.loadFromString("37376").equals(EtherTypes.CISCOQINQ)); + Assert.assertTrue(EtherTypes.loadFromString("100") == null); + } + +} + + + diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/HexEncodeTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/HexEncodeTest.java new file mode 100644 index 0000000000..b9b5f45927 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/HexEncodeTest.java @@ -0,0 +1,70 @@ + +/* + * 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.controller.sal.utils; + +import org.junit.Assert; +import org.junit.Test; + +public class HexEncodeTest { + + @Test + public void testbytesToHexString() { + byte[] bytes1 = {(byte)0x01, (byte)0x02, (byte)0x03}; + String str1 = HexEncode.bytesToHexString(bytes1); + Assert.assertTrue(str1.equals("010203")); + + byte[] bytes2 = {(byte)0x11, (byte)0x22, (byte)0x33}; + String str2 = HexEncode.bytesToHexString(bytes2); + Assert.assertFalse(str2.equals("010203")); + + } + + @Test + public void testLongToHexString() { + long value1 = 12345678L; + String str1 = HexEncode.longToHexString(value1); + Assert.assertTrue(str1.equals("00:00:00:00:00:bc:61:4e")); + + long value2 = 98765432L; + String str2 = HexEncode.longToHexString(value2); + Assert.assertFalse(str2.equals("00:44:33:22:11:bc:61:4e")); + + } + + @Test + public void testBytesFromHexString() { + String byteStr1 = "00:11:22:33:44:55"; + byte byteArray1[] = new byte[(byteStr1.length() + 1)/3]; + byteArray1 = HexEncode.bytesFromHexString(byteStr1); + + Assert.assertTrue(byteArray1[0] == (byte)0x0); + Assert.assertTrue(byteArray1[1] == (byte)0x11); + Assert.assertTrue(byteArray1[2] == (byte)0x22); + Assert.assertTrue(byteArray1[3] == (byte)0x33); + Assert.assertTrue(byteArray1[4] == (byte)0x44); + Assert.assertTrue(byteArray1[5] == (byte)0x55); + + String byteStr2 = "00:11:22:33:44:55"; + byte byteArray2[] = new byte[(byteStr2.length() + 1)/3]; + byteArray2 = HexEncode.bytesFromHexString(byteStr2); + + Assert.assertFalse(byteArray2[0] == (byte)0x55); + Assert.assertFalse(byteArray2[1] == (byte)0x44); + Assert.assertFalse(byteArray2[2] == (byte)0x33); + Assert.assertFalse(byteArray2[3] == (byte)0x22); + Assert.assertFalse(byteArray2[4] == (byte)0x11); + Assert.assertFalse(byteArray2[5] == (byte)0x0); + + } + +} + + + diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/NetUtilsTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/NetUtilsTest.java new file mode 100644 index 0000000000..77d1fe2164 --- /dev/null +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/NetUtilsTest.java @@ -0,0 +1,277 @@ + +/* + * 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.controller.sal.utils; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.utils.NetUtils; + +public class NetUtilsTest { + + @Test + public void testByteArrayMethods() { + int ip = 8888; + Assert.assertTrue(NetUtils + .byteArray4ToInt(NetUtils.intToByteArray4(ip)) == ip); + + ip = 0xffffffff; + Assert.assertTrue(NetUtils + .byteArray4ToInt(NetUtils.intToByteArray4(ip)) == ip); + + ip = 0; + Assert.assertTrue(NetUtils + .byteArray4ToInt(NetUtils.intToByteArray4(ip)) == ip); + + ip = 0x1fffffff; + Assert.assertTrue(NetUtils + .byteArray4ToInt(NetUtils.intToByteArray4(ip)) == ip); + + ip = 0xfffffff; + Assert.assertTrue(NetUtils + .byteArray4ToInt(NetUtils.intToByteArray4(ip)) == ip); + + ip = 0xf000ffff; + Assert.assertTrue(NetUtils + .byteArray4ToInt(NetUtils.intToByteArray4(ip)) == ip); + + byte ba[] = { (byte) 0xf, (byte) 0xf, (byte) 0xf, (byte) 0xff }; + Assert.assertTrue(Arrays.equals(ba, NetUtils.intToByteArray4(NetUtils + .byteArray4ToInt(ba)))); + + byte ba1[] = { (byte) 255, (byte) 255, (byte) 255, (byte) 255 }; + Assert.assertTrue(Arrays.equals(ba1, NetUtils.intToByteArray4(NetUtils + .byteArray4ToInt(ba1)))); + + byte ba2[] = { (byte) 255, (byte) 0, (byte) 0, (byte) 0 }; + Assert.assertTrue(Arrays.equals(ba2, NetUtils.intToByteArray4(NetUtils + .byteArray4ToInt(ba2)))); + + byte ba3[] = { (byte) 0, (byte) 0, (byte) 0, (byte) 0 }; + Assert.assertTrue(Arrays.equals(ba3, NetUtils.intToByteArray4(NetUtils + .byteArray4ToInt(ba3)))); + + byte ba4[] = { (byte) 255, (byte) 128, (byte) 0, (byte) 0 }; + Assert.assertTrue(Arrays.equals(ba4, NetUtils.intToByteArray4(NetUtils + .byteArray4ToInt(ba4)))); + } + + @Test + public void testInetMethods() throws UnknownHostException { + int ip = 0xfffffff0; + InetAddress inet = InetAddress.getByName("255.255.255.240"); + Assert.assertTrue(inet.equals(NetUtils.getInetAddress(ip))); + + ip = 0; + inet = InetAddress.getByName("0.0.0.0"); + Assert.assertTrue(inet.equals(NetUtils.getInetAddress(ip))); + + ip = 0x9ffff09; + inet = InetAddress.getByName("9.255.255.9"); + Assert.assertTrue(inet.equals(NetUtils.getInetAddress(ip))); + } + + @Test + public void testMasksV4() throws UnknownHostException { + + InetAddress mask = InetAddress.getByName("128.0.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(1, false))); + + mask = InetAddress.getByName("192.0.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(2, false))); + + mask = InetAddress.getByName("224.0.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(3, false))); + + mask = InetAddress.getByName("240.0.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(4, false))); + + mask = InetAddress.getByName("248.0.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(5, false))); + + mask = InetAddress.getByName("252.0.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(6, false))); + + mask = InetAddress.getByName("254.0.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(7, false))); + + mask = InetAddress.getByName("255.0.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(8, false))); + + mask = InetAddress.getByName("255.128.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(9, false))); + + mask = InetAddress.getByName("255.192.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(10, false))); + + mask = InetAddress.getByName("255.224.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(11, false))); + + mask = InetAddress.getByName("255.240.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(12, false))); + + mask = InetAddress.getByName("255.248.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(13, false))); + + mask = InetAddress.getByName("255.252.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(14, false))); + + mask = InetAddress.getByName("255.254.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(15, false))); + + mask = InetAddress.getByName("255.255.0.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(16, false))); + + mask = InetAddress.getByName("255.255.128.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(17, false))); + + mask = InetAddress.getByName("255.255.192.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(18, false))); + + mask = InetAddress.getByName("255.255.224.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(19, false))); + + mask = InetAddress.getByName("255.255.240.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(20, false))); + + mask = InetAddress.getByName("255.255.248.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(21, false))); + + mask = InetAddress.getByName("255.255.252.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(22, false))); + + mask = InetAddress.getByName("255.255.254.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(23, false))); + + mask = InetAddress.getByName("255.255.255.0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(24, false))); + + mask = InetAddress.getByName("255.255.255.128"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(25, false))); + + mask = InetAddress.getByName("255.255.255.192"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(26, false))); + + mask = InetAddress.getByName("255.255.255.224"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(27, false))); + + mask = InetAddress.getByName("255.255.255.240"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(28, false))); + + mask = InetAddress.getByName("255.255.255.248"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(29, false))); + + mask = InetAddress.getByName("255.255.255.252"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(30, false))); + + mask = InetAddress.getByName("255.255.255.254"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(31, false))); + + mask = InetAddress.getByName("255.255.255.255"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(32, false))); + } + + @Test + public void testMasksV6() throws UnknownHostException { + + InetAddress mask = InetAddress.getByName("ff00::0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(8, true))); + + mask = InetAddress.getByName("8000::0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(1, true))); + + mask = InetAddress.getByName("f800::0"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(5, true))); + + mask = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"); + Assert.assertTrue(mask.equals(NetUtils.getInetNetworkMask(127, true))); + } + + @Test + public void testGetSubnetLen() { + + byte address[] = { (byte) 128, (byte) 0, (byte) 0, 0 }; + Assert.assertTrue(NetUtils.getSubnetMaskLength(address) == 31); + + byte address1[] = { (byte) 255, 0, 0, 0 }; + Assert.assertTrue(NetUtils.getSubnetMaskLength(address1) == 24); + + byte address2[] = { (byte) 255, (byte) 255, (byte) 248, 0 }; + Assert.assertTrue(NetUtils.getSubnetMaskLength(address2) == 11); + + byte address4[] = { (byte) 255, (byte) 255, (byte) 255, (byte) 254 }; + Assert.assertTrue(NetUtils.getSubnetMaskLength(address4) == 1); + } + + @Test + public void testGetSubnetPrefix() throws UnknownHostException { + InetAddress ip = InetAddress.getByName("192.128.64.252"); + int maskLen = 25; + Assert.assertTrue(NetUtils.getSubnetPrefix(ip, maskLen).equals( + InetAddress.getByName("192.128.64.128"))); + } + + @Test + public void testIsIPv6Valid() throws UnknownHostException { + Assert.assertTrue(NetUtils + .isIPv6AddressValid("fe80:0000:0000:0000:0204:61ff:fe9d:f156")); //normal ipv6 + Assert.assertTrue(NetUtils + .isIPv6AddressValid("fe80:0:0:0:204:61ff:fe9d:f156")); //no leading zeroes + Assert.assertTrue(NetUtils + .isIPv6AddressValid("fe80::204:61ff:fe9d:f156")); //zeroes to :: + Assert + .assertTrue(NetUtils + .isIPv6AddressValid("fe80:0000:0000:0000:0204:61ff:254.157.241.86")); // ipv4 ending + Assert.assertTrue(NetUtils + .isIPv6AddressValid("fe80:0:0:0:0204:61ff:254.157.241.86")); // no leading zeroes, ipv4 end + Assert.assertTrue(NetUtils + .isIPv6AddressValid("fe80::204:61ff:254.157.241.86")); // zeroes ::, no leading zeroes + + Assert.assertTrue(NetUtils.isIPv6AddressValid("2001::")); //link-local prefix + Assert.assertTrue(NetUtils.isIPv6AddressValid("::1")); //localhost + Assert.assertTrue(NetUtils.isIPv6AddressValid("fe80::")); //global-unicast + Assert.assertFalse(NetUtils.isIPv6AddressValid("abcd")); //not valid + Assert.assertFalse(NetUtils.isIPv6AddressValid("1")); //not valid + Assert.assertFalse(NetUtils + .isIPv6AddressValid("fe80:0:0:0:204:61ff:fe9d")); //not valid, too short + Assert.assertFalse(NetUtils + .isIPv6AddressValid("fe80:::0:0:0:204:61ff:fe9d")); //not valid + Assert.assertFalse(NetUtils.isIPv6AddressValid("192.168.1.1")); //not valid,ipv4 + Assert + .assertFalse(NetUtils + .isIPv6AddressValid("2001:0000:1234:0000:10001:C1C0:ABCD:0876")); //not valid, extra number + Assert + .assertFalse(NetUtils + .isIPv6AddressValid("20010:0000:1234:0000:10001:C1C0:ABCD:0876")); //not valid, extra number + + Assert + .assertTrue(NetUtils + .isIPv6AddressValid("2001:0DB8:0000:CD30:0000:0000:0000:0000/60")); //full with mask + Assert.assertTrue(NetUtils.isIPv6AddressValid("2001:0DB8:0:CD30::/64")); //shortened with mask + Assert.assertTrue(NetUtils.isIPv6AddressValid("2001:0DB8:0:CD30::/0")); //0 subnet with mask + Assert.assertTrue(NetUtils.isIPv6AddressValid("::1/128")); //localhost 128 mask + + Assert.assertFalse(NetUtils.isIPv6AddressValid("124.15.6.89/60")); //invalid, ip with mask + Assert + .assertFalse(NetUtils + .isIPv6AddressValid("2001:0DB8:0000:CD30:0000:0000:0000:0000/130")); //invalid, mask >128 + Assert + .assertFalse(NetUtils + .isIPv6AddressValid("2001:0DB8:0:CD30::/-5")); //invalid, mask < 0 + Assert.assertFalse(NetUtils + .isIPv6AddressValid("fe80:::0:0:0:204:61ff:fe9d/64")); //not valid ip, valid netmask + Assert.assertFalse(NetUtils + .isIPv6AddressValid("fe80:::0:0:0:204:61ff:fe9d/-1")); //not valid both + + } +} diff --git a/opendaylight/sal/implementation/pom.xml b/opendaylight/sal/implementation/pom.xml new file mode 100644 index 0000000000..32f0a38157 --- /dev/null +++ b/opendaylight/sal/implementation/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + org.opendaylight.controller + sal.implementation + 0.4.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.slf4j, + org.apache.commons.lang3.builder, + org.opendaylight.controller.sal.core, + org.opendaylight.controller.sal.packet, + org.opendaylight.controller.sal.inventory, + org.opendaylight.controller.sal.flowprogrammer, + org.opendaylight.controller.sal.reader, + org.opendaylight.controller.sal.topology, + org.opendaylight.controller.sal.action, + org.opendaylight.controller.sal.match, + org.opendaylight.controller.sal.utils, + org.apache.felix.dm, + org.eclipse.osgi.framework.console, + org.osgi.framework + + + + + org.opendaylight.controller.sal.implementation.internal.Activator + + + + + + + + + org.opendaylight.controller + sal + 0.4.0-SNAPSHOT + + + diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Activator.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Activator.java new file mode 100644 index 0000000000..1d7732af44 --- /dev/null +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Activator.java @@ -0,0 +1,166 @@ + +/* + * 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.controller.sal.implementation.internal; + +import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; +import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService; +import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService; +import org.opendaylight.controller.sal.inventory.IInventoryService; +import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates; +import org.opendaylight.controller.sal.inventory.IPluginInInventoryService; +import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService; +import org.opendaylight.controller.sal.packet.IDataPacketService; +import org.opendaylight.controller.sal.packet.IListenDataPacket; +import org.opendaylight.controller.sal.packet.IPluginInDataPacketService; +import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService; +import org.opendaylight.controller.sal.reader.IPluginInReadService; +import org.opendaylight.controller.sal.reader.IReadService; +import org.opendaylight.controller.sal.topology.IListenTopoUpdates; +import org.opendaylight.controller.sal.topology.IPluginInTopologyService; +import org.opendaylight.controller.sal.topology.IPluginOutTopologyService; +import org.opendaylight.controller.sal.topology.ITopologyService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.felix.dm.Component; + +public class Activator extends ComponentActivatorAbstractBase { + protected static final Logger logger = LoggerFactory + .getLogger(Activator.class); + + /** + * Function called when the activator starts just after some + * initializations are done by the + * ComponentActivatorAbstractBase. + * + */ + public void init() { + + } + + /** + * Function called when the activator stops just before the + * cleanup done by ComponentActivatorAbstractBase + * + */ + public void destroy() { + + } + + /** + * Function that is used to communicate to dependency manager the + * list of known implementations for services inside a container + * + * + * @return An array containing all the CLASS objects that will be + * instantiated in order to get an fully working implementation + * Object + */ + public Object[] getImplementations() { + Object[] res = { Topology.class, Inventory.class, + FlowProgrammerService.class, ReadService.class, + DataPacketService.class }; + return res; + } + + /** + * Function that is called when configuration of the dependencies + * is required. + * + * @param c dependency manager Component object, used for + * configuring the dependencies exported and imported + * @param imp Implementation class that is being configured, + * needed as long as the same routine can configure multiple + * implementations + * @param containerName The containerName being configured, this allow + * also optional per-container different behavior if needed, usually + * should not be the case though. + */ + public void configureInstance(Component c, Object imp, String containerName) { + if (imp.equals(Topology.class)) { + // export the service for Apps and Plugins + c.setInterface(new String[] { + IPluginOutTopologyService.class.getName(), + ITopologyService.class.getName() }, null); + + // There can be multiple Topology listeners or there could + // be none, hence the dependency is optional + c.add(createContainerServiceDependency(containerName).setService( + IListenTopoUpdates.class).setCallbacks("setUpdateService", + "unsetUpdateService").setRequired(false)); + + // There can be multiple southbound plugins or there could + // be none, the dependency is optional + c.add(createContainerServiceDependency(containerName).setService( + IPluginInTopologyService.class).setCallbacks( + "setPluginService", "unsetPluginService") + .setRequired(false)); + } + + if (imp.equals(Inventory.class)) { + // export the service + c.setInterface(new String[] { + IPluginOutInventoryService.class.getName(), + IInventoryService.class.getName() }, null); + + // Now lets add a service dependency to make sure the + // provider of service exists + c.add(createContainerServiceDependency(containerName).setService( + IListenInventoryUpdates.class).setCallbacks( + "setUpdateService", "unsetUpdateService") + .setRequired(false)); + c + .add(createContainerServiceDependency(containerName) + .setService(IPluginInInventoryService.class) + .setCallbacks("setPluginService", + "unsetPluginService").setRequired(true)); + } + + if (imp.equals(FlowProgrammerService.class)) { + // It is the provider of IFlowProgrammerService + c.setInterface(IFlowProgrammerService.class.getName(), null); + //It is also the consumer of IPluginInFlowProgrammerService + c.add(createServiceDependency().setService( + IPluginInFlowProgrammerService.class).setCallbacks( + "setService", "unsetService").setRequired(true)); + } + + if (imp.equals(ReadService.class)) { + // It is the provider of IReadService + c.setInterface(IReadService.class.getName(), null); + + //It is also the consumer of IPluginInReadService + c.add(createContainerServiceDependency(containerName).setService( + IPluginInReadService.class).setCallbacks("setService", + "unsetService").setRequired(true)); + } + + /************************/ + /* DATA PACKET SERVICES */ + /************************/ + if (imp.equals(DataPacketService.class)) { + c.setInterface(new String[] { + IPluginOutDataPacketService.class.getName(), + IDataPacketService.class.getName() }, null); + + // Optionally use PluginInDataService if any southbound + // protocol plugin exists + c.add(createContainerServiceDependency(containerName).setService( + IPluginInDataPacketService.class).setCallbacks( + "setPluginInDataService", "unsetPluginInDataService") + .setRequired(false)); + + // Optionally listed to IListenDataPacket services + c.add(createContainerServiceDependency(containerName).setService( + IListenDataPacket.class).setCallbacks( + "setListenDataPacket", "unsetListenDataPacket") + .setRequired(false)); + } + } +} diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/DataPacketService.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/DataPacketService.java new file mode 100644 index 0000000000..fe525bb081 --- /dev/null +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/DataPacketService.java @@ -0,0 +1,554 @@ + +/* + * 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 + */ + +/** + * @file DataPacketService.java + * + * @brief Implementation of Data Packet services in SAL + * + * Implementation of Data Packet services in SAL + */ + +package org.opendaylight.controller.sal.implementation.internal; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.packet.Ethernet; +import org.opendaylight.controller.sal.packet.IDataPacketService; +import org.opendaylight.controller.sal.packet.IListenDataPacket; +import org.opendaylight.controller.sal.packet.IPluginInDataPacketService; +import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService; +import org.opendaylight.controller.sal.packet.LinkEncap; +import org.opendaylight.controller.sal.packet.Packet; +import org.opendaylight.controller.sal.packet.PacketResult; +import org.opendaylight.controller.sal.packet.RawPacket; +import org.opendaylight.controller.sal.utils.NetUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DataPacketService implements IPluginOutDataPacketService, + IDataPacketService { + private int RXMAXQUEUESIZE = 1000; + private int TXMAXQUEUESIZE = 1000; + protected static final Logger logger = LoggerFactory + .getLogger(DataPacketService.class); + /** + * Database that associates one NodeIDType to the + * IPluginDataPacketService, in fact we expect that there will be + * one instance of IPluginDataPacketService for each southbound + * plugin. + * Using the ConcurrentHashMap because the threads that will be + * adding a new service, removing a service, going through all of + * them maybe different. + */ + private ConcurrentHashMap + pluginInDataService = + new ConcurrentHashMap(); + private Map statistics = new HashMap(); + /** + * Queue for packets received from Data Path + */ + private LinkedBlockingQueue rxQueue = new LinkedBlockingQueue( + RXMAXQUEUESIZE); + /** + * Queue for packets that need to be transmitted to Data Path + */ + private LinkedBlockingQueue txQueue = new LinkedBlockingQueue( + RXMAXQUEUESIZE); + /** + * Transmission thread + */ + private Thread txThread = new Thread(new TxLoop(), + "DataPacketService TX thread"); + /** + * Receiving thread + */ + private Thread rxThread = new Thread(new RxLoop(), + "DataPacketService RX thread"); + + /** + * Representation of a Data Packet Listener including of its + * properties + * + */ + private class DataPacketListener { + // Key fields + private String listenerName; + // Attribute fields + private IListenDataPacket listener; + private String dependency; + private Match match; + + DataPacketListener(String name, IListenDataPacket s, String dependency, + Match match) { + this.listenerName = name; + this.listener = s; + this.dependency = dependency; + this.match = match; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + DataPacketListener rhs = (DataPacketListener) obj; + return new EqualsBuilder().append(this.listenerName, + rhs.listenerName).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(13, 31).append(listenerName) + .toHashCode(); + } + } + + /** + * This very expensive version of List is being used because it + * work well in concurrent situation, as we expect new service + * addition, service removal and walk of the service will happen + * from different places + */ + private List> listenDataPacket = new CopyOnWriteArrayList>(); + // Quick index to make sure there are no duplicate elements + private Set indexDataPacket = Collections + .synchronizedSet(new HashSet()); + + /** + * Loop for processing Received packets + * + */ + private class RxLoop implements Runnable { + public void run() { + RawPacket pkt; + try { + for (pkt = rxQueue.take(); pkt != null; pkt = rxQueue.take()) { + for (List serialListeners : listenDataPacket) { + int i = 0; + for (i = 0; i < serialListeners.size(); i++) { + RawPacket copyPkt = null; + try { + copyPkt = new RawPacket(pkt); + } catch (ConstructionException cex) { + logger.debug("Error while cloning the packet"); + } + if (copyPkt == null) { + increaseStat("RXPacketCopyFailed"); + continue; + } + DataPacketListener l = serialListeners.get(i); + IListenDataPacket s = (l == null ? null + : l.listener); + if (s != null) { + try { + // TODO Make sure to filter based + // on the match too, later on + PacketResult res = s + .receiveDataPacket(copyPkt); + increaseStat("RXPacketSuccess"); + if (res.equals(PacketResult.CONSUME)) { + increaseStat("RXPacketSerialExit"); + break; + } + } catch (Exception e) { + increaseStat("RXPacketFailedForException"); + } + } + } + } + } + } catch (InterruptedException e) { + // Not a big deal + } + } + } + + /** + * Loop for processing packets to be transmitted + * + */ + private class TxLoop implements Runnable { + public void run() { + RawPacket pkt; + try { + for (pkt = txQueue.take(); pkt != null; pkt = txQueue.take()) { + // Retrieve outgoing node connector so to send out + // the packet to corresponding node + NodeConnector p = pkt.getOutgoingNodeConnector(); + if (p != null) { + String t = p.getNode() + .getType(); + // Now locate the TX dispatcher + IPluginInDataPacketService s = pluginInDataService + .get(t); + if (s != null) { + try { + s.transmitDataPacket(pkt); + increaseStat("TXPacketSuccess"); + } catch (Exception e) { + increaseStat("TXPacketFailedForException"); + } + } else { + increaseStat("TXpluginNotFound"); + } + } + } + } catch (InterruptedException e) { + // Not a big deal + } + } + } + + void setPluginInDataService(Map props, IPluginInDataPacketService s) { + if (this.pluginInDataService == null) { + logger.error("pluginInDataService store null"); + return; + } + String type = null; + logger.trace("Received setPluginInDataService request"); + for (Object e : props.entrySet()) { + Map.Entry entry = (Map.Entry) e; + logger.trace("Prop key:(" + entry.getKey() + ") value:(" + + entry.getValue() + ")"); + } + + Object value = props.get("protocolPluginType"); + if (value instanceof String) { + type = (String) value; + } + if (type == null) { + logger.error("Received a PluginInDataService without any " + + "protocolPluginType provided"); + } else { + this.pluginInDataService.put(type, s); + logger.debug("Stored the PluginInDataService for type:" + type); + } + } + + void unsetPluginInDataService(Map props, IPluginInDataPacketService s) { + if (this.pluginInDataService == null) { + logger.error("pluginInDataService store null"); + return; + } + + String type = null; + logger.trace("Received unsetPluginInDataService request"); + for (Object e : props.entrySet()) { + Map.Entry entry = (Map.Entry) e; + logger.trace("Prop key:(" + entry.getKey() + ") value:(" + + entry.getValue() + ")"); + } + + Object value = props.get("protocoloPluginType"); + if (value instanceof String) { + type = (String) value; + } + if (type == null) { + logger.error("Received a PluginInDataService without any " + + "protocolPluginType provided"); + } else if (this.pluginInDataService.get(type).equals(s)) { + this.pluginInDataService.remove(type); + logger.debug("Removed the PluginInDataService for type:" + type); + } + } + + void setListenDataPacket(Map props, IListenDataPacket s) { + if (this.listenDataPacket == null || this.indexDataPacket == null) { + logger.error("data structure to store data is NULL"); + return; + } + logger.trace("Received setListenDataPacket request"); + for (Object e : props.entrySet()) { + Map.Entry entry = (Map.Entry) e; + logger.trace("Prop key:(" + entry.getKey() + ") value:(" + + entry.getValue() + ")"); + } + + String listenerName = null; + String listenerDependency = null; + Match filter = null; + Object value; + // Read the listenerName + value = props.get("salListenerName"); + if (value instanceof String) { + listenerName = (String) value; + } + + if (listenerName == null) { + logger.error("Trying to set a listener without a Name"); + return; + } + + //Read the dependency + value = props.get("salListenerDependency"); + if (value instanceof String) { + listenerDependency = (String) value; + } + + //Read match filter if any + value = props.get("salListenerFilter"); + if (value instanceof Match) { + filter = (Match) value; + } + + DataPacketListener l = new DataPacketListener(listenerName, s, + listenerDependency, filter); + + DataPacketListener lDependency = new DataPacketListener( + listenerDependency, null, null, null); + + // Now let see if there is any dependency + if (listenerDependency == null) { + logger.debug("listener without any dependency"); + if (this.indexDataPacket.contains(l)) { + logger.error("trying to add an existing element"); + } else { + logger.debug("adding listener: " + listenerName); + CopyOnWriteArrayList serialListeners = new CopyOnWriteArrayList(); + serialListeners.add(l); + this.listenDataPacket.add(serialListeners); + this.indexDataPacket.add(l); + } + } else { + logger.debug("listener with dependency"); + // Now search for the dependency and put things in order + if (this.indexDataPacket.contains(l)) { + logger.error("trying to add an existing element"); + } else { + logger.debug("adding listener: " + listenerName); + // Lets find the set with the dependency in it, if we + // find it lets just add our dependency at the end of + // the list. + for (List serialListeners : this.listenDataPacket) { + int i = 0; + boolean done = false; + if (serialListeners.contains(lDependency)) { + serialListeners.add(l); + done = true; + } + // If we did fine the element, lets break early + if (done) { + break; + } + } + + this.indexDataPacket.add(l); + } + } + } + + void unsetListenDataPacket(Map props, IListenDataPacket s) { + if (this.listenDataPacket == null || this.indexDataPacket == null) { + logger.error("data structure to store data is NULL"); + return; + } + logger.trace("Received UNsetListenDataPacket request"); + for (Object e : props.entrySet()) { + Map.Entry entry = (Map.Entry) e; + logger.trace("Prop key:(" + entry.getKey() + ") value:(" + + entry.getValue() + ")"); + } + + String listenerName = null; + Object value; + // Read the listenerName + value = props.get("salListenerName"); + if (value instanceof String) { + listenerName = (String) value; + } + + if (listenerName == null) { + logger.error("Trying to set a listener without a Name"); + return; + } + + DataPacketListener l = new DataPacketListener(listenerName, s, null, + null); + if (!this.indexDataPacket.contains(l)) { + logger.error("trying to remove a non-existing element"); + } else { + logger.debug("removing listener: " + listenerName); + for (List serialListeners : this.listenDataPacket) { + int i = 0; + boolean done = false; + for (i = 0; i < serialListeners.size(); i++) { + if (serialListeners.get(i).equals(l)) { + serialListeners.remove(i); + done = true; + break; + } + } + // Now remove a serialListener that maybe empty + if (serialListeners.isEmpty()) { + this.listenDataPacket.remove(serialListeners); + } + // If we did fine the element, lets break early + if (done) { + break; + } + } + + this.indexDataPacket.remove(l); + } + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init() { + this.txThread.start(); + this.rxThread.start(); + } + + /** + * Function called by the dependency manager when at least one + * dependency become unsatisfied or when the component is shutting + * down because for example bundle is being stopped. + * + */ + void destroy() { + // Make sure to cleanup the data structure we use to track + // services + this.listenDataPacket.clear(); + this.indexDataPacket.clear(); + this.pluginInDataService.clear(); + this.statistics.clear(); + this.rxQueue.clear(); + this.txQueue.clear(); + this.txThread.interrupt(); + this.rxThread.interrupt(); + // Wait for them to be done + try { + this.txThread.join(); + this.rxThread.join(); + } catch (InterruptedException ex) { + // Not a big deal + } + } + + private void increaseStat(String name) { + if (this.statistics == null) { + return; + } + + AtomicInteger currValue = null; + synchronized (this.statistics) { + currValue = this.statistics.get(name); + + if (currValue == null) { + this.statistics.put(name, new AtomicInteger(0)); + return; + } + } + currValue.incrementAndGet(); + } + + @Override + public PacketResult receiveDataPacket(RawPacket inPkt) { + if (inPkt.getIncomingNodeConnector() == null) { + increaseStat("nullIncomingNodeConnector"); + return PacketResult.IGNORED; + } + + // If the queue was full don't wait, rather increase a counter + // for it + if (!this.rxQueue.offer(inPkt)) { + increaseStat("fullRXQueue"); + return PacketResult.IGNORED; + } + + // Walk the chain of listener going first throw all the + // parallel ones and for each parallel in serial + return PacketResult.IGNORED; + } + + @Override + public void transmitDataPacket(RawPacket outPkt) { + if (outPkt.getOutgoingNodeConnector() == null) { + increaseStat("nullOutgoingNodeConnector"); + return; + } + + if (!this.txQueue.offer(outPkt)) { + increaseStat("fullTXQueue"); + return; + } + } + + @Override + public Packet decodeDataPacket(RawPacket pkt) { + // Sanity checks + if (pkt == null) { + return null; + } + byte[] data = pkt.getPacketData(); + if (data.length <= 0) { + return null; + } + if (pkt.getEncap().equals(LinkEncap.ETHERNET)) { + Ethernet res = new Ethernet(); + try { + res.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte); + } catch (Exception e) { + logger.warn("", e); + } + return res; + } + return null; + } + + @Override + public RawPacket encodeDataPacket(Packet pkt) { + // Sanity checks + if (pkt == null) { + return null; + } + byte[] data; + try { + data = pkt.serialize(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + if (data.length <= 0) { + return null; + } + try { + RawPacket res = new RawPacket(data); + return res; + } catch (ConstructionException cex) { + } + // If something goes wrong then we have to return null + return null; + } +} diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java new file mode 100644 index 0000000000..cb0a5c77a6 --- /dev/null +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java @@ -0,0 +1,421 @@ + +/* + * 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.controller.sal.implementation.internal; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.osgi.framework.console.CommandInterpreter; +import org.eclipse.osgi.framework.console.CommandProvider; +import org.opendaylight.controller.sal.action.Action; +import org.opendaylight.controller.sal.action.Controller; +import org.opendaylight.controller.sal.action.Flood; +import org.opendaylight.controller.sal.action.Output; +import org.opendaylight.controller.sal.action.PopVlan; +import org.opendaylight.controller.sal.action.SetNwDst; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Node.NodeIDType; +import org.opendaylight.controller.sal.flowprogrammer.Flow; +import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService; +import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; +import org.opendaylight.controller.sal.utils.StatusCode; +import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.IPProtocols; +import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.opendaylight.controller.sal.utils.Status; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The SAL Flow Programmer Service. It dispatches the flow programming + * requests to the proper SDN protocol plugin + * + * + * + */ +public class FlowProgrammerService implements IFlowProgrammerService, + CommandProvider { + + protected static final Logger logger = LoggerFactory + .getLogger(FlowProgrammerService.class); + private ConcurrentHashMap + pluginFlowProgrammer = + new ConcurrentHashMap(); + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init() { + logger.debug("INIT called!"); + } + + /** + * Function called by the dependency manager when at least one + * dependency become unsatisfied or when the component is shutting + * down because for example bundle is being stopped. + * + */ + void destroy() { + // Clear previous registration to avoid they are left hanging + this.pluginFlowProgrammer.clear(); + logger.debug("DESTROY called!"); + } + + /** + * Function called by dependency manager after "init ()" is called + * and after the services provided by the class are registered in + * the service registry + * + */ + void start() { + logger.debug("START called!"); + // OSGI console + registerWithOSGIConsole(); + } + + /** + * Function called by the dependency manager before the services + * exported by the component are unregistered, this will be + * followed by a "destroy ()" calls + * + */ + void stop() { + logger.debug("STOP called!"); + } + + // Set the reference to the plugin flow programmer + public void setService(Map props, IPluginInFlowProgrammerService s) { + if (this.pluginFlowProgrammer == null) { + logger.error("pluginFlowProgrammer store null"); + return; + } + + logger.trace("Got a service set request {}", s); + String type = null; + for (Object e : props.entrySet()) { + Map.Entry entry = (Map.Entry) e; + logger.trace("Prop key:(" + entry.getKey() + ") value:(" + + entry.getValue() + ")"); + } + + Object value = props.get("protocolPluginType"); + if (value instanceof String) { + type = (String) value; + } + if (type == null) { + logger.error("Received a pluginFlowProgrammer without any " + + "protocolPluginType provided"); + } else { + this.pluginFlowProgrammer.put(type, s); + logger.debug("Stored the pluginFlowProgrammer for type:" + type); + } + } + + public void unsetService(Map props, + IPluginInFlowProgrammerService s) { + if (this.pluginFlowProgrammer == null) { + logger.error("pluginFlowProgrammer store null"); + return; + } + + String type = null; + logger.debug("Received unsetpluginFlowProgrammer request"); + for (Object e : props.entrySet()) { + Map.Entry entry = (Map.Entry) e; + logger.trace("Prop key:(" + entry.getKey() + ") value:(" + + entry.getValue() + ")"); + } + + Object value = props.get("protocoloPluginType"); + if (value instanceof String) { + type = (String) value; + } + if (type == null) { + logger.error("Received a pluginFlowProgrammer without any " + + "protocolPluginType provided"); + } else if (this.pluginFlowProgrammer.get(type).equals(s)) { + this.pluginFlowProgrammer.remove(type); + logger.debug("Removed the pluginFlowProgrammer for type:" + type); + } + } + + @Override + public Status addFlow(Node node, Flow flow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .addFlow(node, flow); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status removeFlow(Node node, Flow flow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .removeFlow(node, flow); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status removeAllFlows(Node node) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .removeAllFlows(node); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status modifyFlow(Node node, Flow oldFlow, Flow newFlow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .modifyFlow(node, oldFlow, newFlow); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + // ---------------- OSGI TEST CODE ------------------------------// + + private void registerWithOSGIConsole() { + BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()) + .getBundleContext(); + bundleContext.registerService(CommandProvider.class.getName(), this, + null); + } + + @Override + public String getHelp() { + StringBuffer help = new StringBuffer(); + help.append("---SAL Flow Programmer testing commands---\n"); + help + .append("\t addflow - Add a sample flow to the openflow switch \n"); + help + .append("\t removeflow - Remove the sample flow from the openflow switch \n"); + return help.toString(); + } + + public void _addflow(CommandInterpreter ci) throws UnknownHostException { + Node node = null; + String nodeId = ci.nextArgument(); + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + ci.println(this.addFlow(node, getSampleFlow(node))); + } + + public void _modifyflow(CommandInterpreter ci) throws UnknownHostException { + Node node = null; + String nodeId = ci.nextArgument(); + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + Flow flowA = getSampleFlow(node); + Flow flowB = getSampleFlow(node); + Match matchB = flowB.getMatch(); + matchB.setField(MatchType.NW_DST, InetAddress + .getByName("190.190.190.190")); + flowB.setMatch(matchB); + ci.println(this.modifyFlow(node, flowA, flowB)); + } + + public void _removeflow(CommandInterpreter ci) throws UnknownHostException { + Node node = null; + String nodeId = ci.nextArgument(); + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + ci.println(this.removeFlow(node, getSampleFlow(node))); + } + + public void _addflowv6(CommandInterpreter ci) throws UnknownHostException { + Node node = null; + String nodeId = ci.nextArgument(); + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + ci.println(this.addFlow(node, getSampleFlowV6(node))); + } + + public void _removeflowv6(CommandInterpreter ci) + throws UnknownHostException { + Node node = null; + String nodeId = ci.nextArgument(); + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + ci.println(this.removeFlow(node, getSampleFlowV6(node))); + } + + private Flow getSampleFlow(Node node) throws UnknownHostException { + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + NodeConnector oport = NodeConnectorCreator.createOFNodeConnector( + (short) 30, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress.getByName("172.28.30.50"); + InetAddress dstIP = InetAddress.getByName("171.71.9.52"); + InetAddress newIP = InetAddress.getByName("200.200.100.1"); + InetAddress ipMask = InetAddress.getByName("255.255.255.0"); + InetAddress ipMask2 = InetAddress.getByName("255.240.0.0"); + short ethertype = EtherTypes.IPv4.shortValue(); + short vlan = (short) 27; + byte vlanPr = 3; + Byte tos = 4; + byte proto = IPProtocols.TCP.byteValue(); + short src = (short) 55000; + short dst = 80; + + /* + * Create a SAL Flow aFlow + */ + Match match = new Match(); + match.setField(MatchType.IN_PORT, port); + match.setField(MatchType.DL_SRC, srcMac); + match.setField(MatchType.DL_DST, dstMac); + match.setField(MatchType.DL_TYPE, ethertype); + match.setField(MatchType.DL_VLAN, vlan); + match.setField(MatchType.DL_VLAN_PR, vlanPr); + match.setField(MatchType.NW_SRC, srcIP, ipMask); + match.setField(MatchType.NW_DST, dstIP, ipMask2); + match.setField(MatchType.NW_TOS, tos); + match.setField(MatchType.NW_PROTO, proto); + match.setField(MatchType.TP_SRC, src); + match.setField(MatchType.TP_DST, dst); + + List actions = new ArrayList(); + actions.add(new SetNwDst(newIP)); + actions.add(new Output(oport)); + actions.add(new PopVlan()); + actions.add(new Flood()); + actions.add(new Controller()); + + Flow flow = new Flow(match, actions); + flow.setPriority((short) 100); + flow.setHardTimeout((short) 360); + + return flow; + } + + private Flow getSampleFlowV6(Node node) throws UnknownHostException { + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + NodeConnector oport = NodeConnectorCreator.createOFNodeConnector( + (short) 30, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress + .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress + .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMask = null; //InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); V6Match implementation assumes no mask is specified + InetAddress ipMask2 = null; //InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + short ethertype = EtherTypes.IPv6.shortValue(); + short vlan = (short) 27; + byte vlanPr = (byte) 3; + Byte tos = 4; + byte proto = IPProtocols.UDP.byteValue(); + short src = (short) 5500; + //short dst = 80; + + /* + * Create a SAL Flow aFlow + */ + Match match = new Match(); + match.setField(MatchType.IN_PORT, port); + match.setField(MatchType.DL_SRC, srcMac); + match.setField(MatchType.DL_DST, dstMac); + match.setField(MatchType.DL_TYPE, ethertype); + match.setField(MatchType.DL_VLAN, vlan); + match.setField(MatchType.DL_VLAN_PR, vlanPr); //V6Match does not handle this properly... + match.setField(MatchType.NW_SRC, srcIP, ipMask); + match.setField(MatchType.NW_DST, dstIP, ipMask2); + match.setField(MatchType.NW_TOS, tos); + match.setField(MatchType.NW_PROTO, proto); + match.setField(MatchType.TP_SRC, src); //V6Match does not handle this properly... + //match.setField(MatchType.TP_DST, dst); V6Match does not handle this properly... + + List actions = new ArrayList(); + actions.add(new Output(oport)); + actions.add(new PopVlan()); + actions.add(new Flood()); + + Flow flow = new Flow(match, actions); + flow.setPriority((short) 300); + flow.setHardTimeout((short) 240); + + return flow; + } +} diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Inventory.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Inventory.java new file mode 100644 index 0000000000..b5f5e2b255 --- /dev/null +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Inventory.java @@ -0,0 +1,134 @@ + +/* + * 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.controller.sal.implementation.internal; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Property; +import org.opendaylight.controller.sal.core.UpdateType; +import org.opendaylight.controller.sal.inventory.IInventoryService; +import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates; +import org.opendaylight.controller.sal.inventory.IPluginInInventoryService; +import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The class describes SAL service to bridge inventory protocol plugin and upper + * applications. One instance per container of the network. + */ +public class Inventory implements IPluginOutInventoryService, IInventoryService { + protected static final Logger logger = LoggerFactory + .getLogger(Inventory.class); + private IListenInventoryUpdates updateService = null; + private IPluginInInventoryService pluginService = null; + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init() { + logger.trace("INIT called!"); + } + + /** + * Function called by the dependency manager when at least one + * dependency become unsatisfied or when the component is shutting + * down because for example bundle is being stopped. + * + */ + void destroy() { + logger.trace("DESTROY called!"); + } + + /** + * Function called by dependency manager after "init ()" is called + * and after the services provided by the class are registered in + * the service registry + * + */ + void start() { + logger.trace("START called!"); + + if (pluginService == null) { + logger.debug("plugin service not avaiable"); + return; + } + } + + /** + * Function called by the dependency manager before the services + * exported by the component are unregistered, this will be + * followed by a "destroy ()" calls + * + */ + void stop() { + logger.trace("STOP called!"); + } + + public void setPluginService(IPluginInInventoryService service) { + logger.trace("Got plugin service set request {}", service); + this.pluginService = service; + } + + public void unsetPluginService(IPluginInInventoryService service) { + logger.trace("Got plugin service UNset request"); + this.pluginService = null; + } + + public void setUpdateService(IListenInventoryUpdates service) { + logger.trace("Got update service set request {}", service); + this.updateService = service; + } + + public void unsetUpdateService(IListenInventoryUpdates service) { + logger.trace("Got a service UNset request"); + this.updateService = null; + } + + @Override + public void updateNode(Node node, UpdateType type, Set props) { + logger.trace("{} {}", node, type); + if (updateService != null) { + updateService.updateNode(node, type, props); + } + } + + @Override + public void updateNodeConnector(NodeConnector nodeConnector, + UpdateType type, Set props) { + logger.trace("{} {}", nodeConnector, type); + + if ((updateService != null) && (type != null)) { + updateService.updateNodeConnector(nodeConnector, type, props); + } + } + + @Override + public ConcurrentMap> getNodeProps() { + if (pluginService != null) + return pluginService.getNodeProps(); + else + return null; + } + + @Override + public ConcurrentMap> getNodeConnectorProps() { + if (pluginService != null) + return pluginService.getNodeConnectorProps(true); + else + return null; + } +} diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/ReadService.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/ReadService.java new file mode 100644 index 0000000000..81bfa5b63f --- /dev/null +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/ReadService.java @@ -0,0 +1,500 @@ + +/* + * 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.controller.sal.implementation.internal; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.osgi.framework.console.CommandInterpreter; +import org.eclipse.osgi.framework.console.CommandProvider; +import org.opendaylight.controller.sal.action.Action; +import org.opendaylight.controller.sal.action.Controller; +import org.opendaylight.controller.sal.action.Flood; +import org.opendaylight.controller.sal.action.Output; +import org.opendaylight.controller.sal.action.PopVlan; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Node.NodeIDType; +import org.opendaylight.controller.sal.flowprogrammer.Flow; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; +import org.opendaylight.controller.sal.reader.FlowOnNode; +import org.opendaylight.controller.sal.reader.IPluginInReadService; +import org.opendaylight.controller.sal.reader.IReadService; +import org.opendaylight.controller.sal.reader.NodeConnectorStatistics; +import org.opendaylight.controller.sal.reader.NodeDescription; +import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.IPProtocols; +import org.opendaylight.controller.sal.utils.NodeConnectorCreator; +import org.opendaylight.controller.sal.utils.NodeCreator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The SAL Read Service. It dispatches the read request to + * the proper SDN protocol plugin + * + * + * + */ +public class ReadService implements IReadService, CommandProvider { + + protected static final Logger logger = LoggerFactory + .getLogger(ReadService.class); + private ConcurrentHashMap + pluginReader = + new ConcurrentHashMap(); + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init() { + } + + /** + * Function called by the dependency manager when at least one + * dependency become unsatisfied or when the component is shutting + * down because for example bundle is being stopped. + * + */ + void destroy() { + // In case of plugin disactivating make sure we clear the + // dependencies + this.pluginReader.clear(); + } + + /** + * Function called by dependency manager after "init ()" is called + * and after the services provided by the class are registered in + * the service registry + * + */ + void start() { + registerWithOSGIConsole(); + } + + /** + * Function called by the dependency manager before the services + * exported by the component are unregistered, this will be + * followed by a "destroy ()" calls + * + */ + void stop() { + } + + // Set the reference to the plugin flow Reader service + public void setService(Map props, IPluginInReadService s) { + if (this.pluginReader == null) { + logger.error("pluginReader store null"); + return; + } + + logger.trace("Got a service set request {}", s); + String type = null; + for (Object e : props.entrySet()) { + Map.Entry entry = (Map.Entry) e; + logger.trace("Prop key:(" + entry.getKey() + ") value:(" + + entry.getValue() + ")"); + } + + Object value = props.get("protocolPluginType"); + if (value instanceof String) { + type = (String) value; + } + if (type == null) { + logger.error("Received a pluginReader without any " + + "protocolPluginType provided"); + } else { + this.pluginReader.put(type, s); + logger.debug("Stored the pluginReader for type:" + type); + } + } + + public void unsetService(Map props, IPluginInReadService s) { + if (this.pluginReader == null) { + logger.error("pluginReader store null"); + return; + } + + String type = null; + logger.debug("Received unsetpluginReader request"); + for (Object e : props.entrySet()) { + Map.Entry entry = (Map.Entry) e; + logger.trace("Prop key:(" + entry.getKey() + ") value:(" + + entry.getValue() + ")"); + } + + Object value = props.get("protocoloPluginType"); + if (value instanceof String) { + type = (String) value; + } + if (type == null) { + logger.error("Received a pluginReader without any " + + "protocolPluginType provided"); + } else if (this.pluginReader.get(type).equals(s)) { + this.pluginReader.remove(type); + logger.debug("Removed the pluginReader for type:" + type); + } + } + + @Override + public FlowOnNode readFlow(Node node, Flow flow) { + if (pluginReader != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readFlow(node, flow, true); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public FlowOnNode nonCachedReadFlow(Node node, Flow flow) { + if (pluginReader != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readFlow(node, flow, false); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public List readAllFlows(Node node) { + if (pluginReader != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readAllFlow(node, true); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public List nonCachedReadAllFlows(Node node) { + if (pluginReader != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readAllFlow(node, false); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public NodeDescription readDescription(Node node) { + if (pluginReader != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readDescription(node, true); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public NodeDescription nonCachedReadDescription(Node node) { + if (pluginReader != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readDescription(node, false); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public NodeConnectorStatistics readNodeConnector(NodeConnector connector) { + Node node = connector.getNode(); + if (pluginReader != null && node != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readNodeConnector(connector, true); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public NodeConnectorStatistics nonCachedReadNodeConnector( + NodeConnector connector) { + Node node = connector.getNode(); + if (pluginReader != null && node != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readNodeConnector(connector, false); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public List readNodeConnectors(Node node) { + if (pluginReader != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readAllNodeConnector(node, true); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public List nonCachedReadNodeConnectors(Node node) { + if (pluginReader != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .readAllNodeConnector(node, false); + } + } + logger.warn("Plugin unuvailable"); + return null; + } + + @Override + public long getTransmitRate(NodeConnector connector) { + Node node = connector.getNode(); + if (pluginReader != null && node != null) { + if (this.pluginReader.get(node.getType()) != null) { + return this.pluginReader.get(node.getType()) + .getTransmitRate(connector); + } + } + logger.warn("Plugin unuvailable"); + return 0; + } + + // ---------------- OSGI TEST CODE ------------------------------// + + private void registerWithOSGIConsole() { + BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()) + .getBundleContext(); + bundleContext.registerService(CommandProvider.class.getName(), this, + null); + } + + @Override + public String getHelp() { + StringBuffer help = new StringBuffer(); + help.append("---SAL Reader testing commands---\n"); + help + .append("\t readflows - Read all the (cached) flows from the openflow switch \n"); + help + .append("\t readflow - Read the (cached) sample flow from the openflow switch \n"); + help + .append("\t readdesc - Read the (cached) description from openflow switch \n"); + help + .append("\t cached=true/false. If false or not specified, the protocol plugin cached info\n"); + help + .append("\t is returned. If true, the info is directly retrieved from the switch\n"); + return help.toString(); + } + + public void _readflows(CommandInterpreter ci) { + String nodeId = ci.nextArgument(); + String cacheReq = ci.nextArgument(); + boolean cached; + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + cached = (cacheReq == null) ? true : cacheReq.equals("true"); + Node node = null; + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + List list = (cached) ? this.readAllFlows(node) : this + .nonCachedReadAllFlows(node); + if (list != null) { + ci.println(list.toString()); + } else { + ci.println("null"); + } + } + + // Requests the hw view for the specific sample flow + public void _readflow(CommandInterpreter ci) throws UnknownHostException { + String nodeId = ci.nextArgument(); + String cacheReq = ci.nextArgument(); + boolean cached; + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + cached = (cacheReq == null) ? true : cacheReq.equals("true"); + Node node = null; + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + Flow flow = getSampleFlow(node); + FlowOnNode flowOnNode = (cached) ? this.readFlow(node, flow) : this + .nonCachedReadFlow(node, flow); + if (flowOnNode != null) { + ci.println(flowOnNode.toString()); + } else { + ci.println("null"); + } + } + + public void _readports(CommandInterpreter ci) { + String nodeId = ci.nextArgument(); + String cacheReq = ci.nextArgument(); + boolean cached; + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + cached = (cacheReq == null) ? true : cacheReq.equals("true"); + Node node = null; + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + List list = (cached) ? this + .readNodeConnectors(node) : this + .nonCachedReadNodeConnectors(node); + if (list != null) { + ci.println(list.toString()); + } else { + ci.println("null"); + } + } + + public void _readport(CommandInterpreter ci) { + String nodeId = ci.nextArgument(); + String portId = ci.nextArgument(); + String cacheReq = ci.nextArgument(); + boolean cached; + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + if (portId == null) { + ci.print("Port id not specified"); + return; + } + cached = (cacheReq == null) ? true : cacheReq.equals("true"); + NodeConnector nodeConnector = null; + Node node = NodeCreator.createOFNode(Long.parseLong(nodeId)); + nodeConnector = NodeConnectorCreator.createNodeConnector(Short + .valueOf(portId), node); + NodeConnectorStatistics stats = (cached) ? this + .readNodeConnector(nodeConnector) : this + .nonCachedReadNodeConnector(nodeConnector); + if (stats != null) { + ci.println(stats.toString()); + } else { + ci.println("null"); + } + } + + public void _readdescr(CommandInterpreter ci) { + String nodeId = ci.nextArgument(); + String cacheReq = ci.nextArgument(); + boolean cached; + if (nodeId == null) { + ci.print("Node id not specified"); + return; + } + cached = (cacheReq == null) ? true : cacheReq.equals("true"); + + Node node = null; + try { + node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (ConstructionException e) { + e.printStackTrace(); + } + NodeDescription desc = (cached) ? this.readDescription(node) : this + .nonCachedReadDescription(node); + if (desc != null) { + ci.println(desc.toString()); + } else { + ci.println("null"); + } + } + + private Flow getSampleFlow(Node node) throws UnknownHostException { + NodeConnector port = NodeConnectorCreator.createOFNodeConnector( + (short) 24, node); + NodeConnector oport = NodeConnectorCreator.createOFNodeConnector( + (short) 30, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, + (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, + (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress.getByName("172.28.30.50"); + InetAddress dstIP = InetAddress.getByName("171.71.9.52"); + InetAddress ipMask = InetAddress.getByName("255.255.255.0"); + InetAddress ipMask2 = InetAddress.getByName("255.0.0.0"); + short ethertype = EtherTypes.IPv4.shortValue(); + short vlan = (short) 27; + byte vlanPr = 3; + Byte tos = 4; + byte proto = IPProtocols.TCP.byteValue(); + short src = (short) 55000; + short dst = 80; + + /* + * Create a SAL Flow aFlow + */ + Match match = new Match(); + match.setField(MatchType.IN_PORT, port); + match.setField(MatchType.DL_SRC, srcMac); + match.setField(MatchType.DL_DST, dstMac); + match.setField(MatchType.DL_TYPE, ethertype); + match.setField(MatchType.DL_VLAN, vlan); + match.setField(MatchType.DL_VLAN_PR, vlanPr); + match.setField(MatchType.NW_SRC, srcIP, ipMask); + match.setField(MatchType.NW_DST, dstIP, ipMask2); + match.setField(MatchType.NW_TOS, tos); + match.setField(MatchType.NW_PROTO, proto); + match.setField(MatchType.TP_SRC, src); + match.setField(MatchType.TP_DST, dst); + + List actions = new ArrayList(); + actions.add(new Output(oport)); + actions.add(new PopVlan()); + actions.add(new Flood()); + actions.add(new Controller()); + return new Flow(match, actions); + } + +} diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Topology.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Topology.java new file mode 100644 index 0000000000..8df566f728 --- /dev/null +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/Topology.java @@ -0,0 +1,118 @@ + +/* + * 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.controller.sal.implementation.internal; + +import java.util.HashSet; +import java.util.Set; +import java.util.Collections; + +import org.opendaylight.controller.sal.core.Edge; +import org.opendaylight.controller.sal.core.Property; +import org.opendaylight.controller.sal.core.UpdateType; +import org.opendaylight.controller.sal.topology.IListenTopoUpdates; +import org.opendaylight.controller.sal.topology.IPluginInTopologyService; +import org.opendaylight.controller.sal.topology.IPluginOutTopologyService; +import org.opendaylight.controller.sal.topology.ITopologyService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Topology implements IPluginOutTopologyService, ITopologyService { + protected static final Logger logger = LoggerFactory + .getLogger(Topology.class); + private Set updateService = Collections + .synchronizedSet(new HashSet()); + private Set pluginService = Collections + .synchronizedSet(new HashSet()); + + void setPluginService(IPluginInTopologyService s) { + if (this.pluginService != null) { + this.pluginService.add(s); + } + } + + void unsetPluginService(IPluginInTopologyService s) { + if (this.pluginService != null) { + this.pluginService.remove(s); + } + } + + void setUpdateService(IListenTopoUpdates s) { + if (this.updateService != null) { + this.updateService.add(s); + } + } + + void unsetUpdateService(IListenTopoUpdates s) { + if (this.updateService != null) { + this.updateService.remove(s); + } + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init() { + } + + /** + * Function called by the dependency manager when at least one + * dependency become unsatisfied or when the component is shutting + * down because for example bundle is being stopped. + * + */ + void destroy() { + // Make sure to clear all the data structure we use to track + // services + if (this.updateService != null) { + this.updateService.clear(); + } + if (this.pluginService != null) { + this.pluginService.clear(); + } + } + + @Override + public void sollicitRefresh() { + synchronized (this.pluginService) { + for (IPluginInTopologyService s : this.pluginService) { + s.sollicitRefresh(); + } + } + } + + @Override + public void edgeUpdate(Edge e, UpdateType type, Set props) { + synchronized (this.updateService) { + for (IListenTopoUpdates s : this.updateService) { + s.edgeUpdate(e, type, props); + } + } + } + + @Override + public void edgeOverUtilized(Edge edge) { + synchronized (this.updateService) { + for (IListenTopoUpdates s : this.updateService) { + s.edgeOverUtilized(edge); + } + } + } + + @Override + public void edgeUtilBackToNormal(Edge edge) { + synchronized (this.updateService) { + for (IListenTopoUpdates s : this.updateService) { + s.edgeUtilBackToNormal(edge); + } + } + } +} diff --git a/opendaylight/sal/implementation/src/test/java/org/opendaylight/controller/sal/implementation/DataPacketServiceTest.java b/opendaylight/sal/implementation/src/test/java/org/opendaylight/controller/sal/implementation/DataPacketServiceTest.java new file mode 100644 index 0000000000..730764a24e --- /dev/null +++ b/opendaylight/sal/implementation/src/test/java/org/opendaylight/controller/sal/implementation/DataPacketServiceTest.java @@ -0,0 +1,180 @@ + +/* + * 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.controller.sal.implementation; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.implementation.internal.DataPacketService; +import org.opendaylight.controller.sal.packet.ARP; +import org.opendaylight.controller.sal.packet.Ethernet; +import org.opendaylight.controller.sal.packet.Packet; +import org.opendaylight.controller.sal.packet.RawPacket; + +public class DataPacketServiceTest { + + @Test + public void DataPacketServiceDecodeTest() throws ConstructionException, InstantiationException, IllegalAccessException { + + DataPacketService dService = new DataPacketService(); + RawPacket rawPkt = null; + + Assert.assertTrue(dService.decodeDataPacket(rawPkt) == null); + + byte[] data = { 10, 12, 14, 20, 55, 69, //DMAC + -90, -20, -100, -82, -78, -97, //SMAC + 8, 6, //ethype + 0, 1, // hw type + 8, 0, // proto (ip) + 6, // hw addr len + 4, // proto addr len + 0, 1, // op codes + -90, -20, -100, -82, -78, -97, //src hw addr + 9, 9, 9, 1, // src proto + 0, 0, 0, 0, 0, 0, // target hw addr + 9, 9, 9, -2 }; // target proto + + rawPkt = new RawPacket(data); + + Packet decodedPkt = dService.decodeDataPacket(rawPkt); + Class payloadClass = ARP.class; + Assert.assertTrue(payloadClass == decodedPkt.getPayload().getClass()); + + ARP arpPacket = (ARP) decodedPkt.getPayload(); + + Assert.assertTrue(arpPacket.getHardwareType() == (byte)0x1); + Assert.assertTrue(arpPacket.getProtocolType() == 2048); + Assert.assertTrue(arpPacket.getHardwareAddressLength() == (byte)0x6); + Assert.assertTrue(arpPacket.getProtocolAddressLength() == (byte)0x4); + Assert.assertTrue(arpPacket.getOpCode() == 1); + + byte[] senderHwAddress = arpPacket.getSenderHardwareAddress(); + byte[] senderProtocolAddress = arpPacket.getSenderProtocolAddress(); + + byte[] targetHwAddress = arpPacket.getTargetHardwareAddress(); + byte[] targetProtocolAddress = arpPacket.getTargetProtocolAddress(); + + + Assert.assertTrue(senderHwAddress[0] == (byte)0xA6); + Assert.assertTrue(senderHwAddress[1] == (byte)0xEC); + Assert.assertTrue(senderHwAddress[2] == (byte)0x9C); + Assert.assertTrue(senderHwAddress[3] == (byte)0xAE); + Assert.assertTrue(senderHwAddress[4] == (byte)0xB2); + Assert.assertTrue(senderHwAddress[5] == (byte)0x9F); + + Assert.assertTrue(senderProtocolAddress[0] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[1] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[2] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[3] == (byte)0x1); + + Assert.assertTrue(targetHwAddress[0] == (byte)0x0); + Assert.assertTrue(targetHwAddress[1] == (byte)0x0); + Assert.assertTrue(targetHwAddress[2] == (byte)0x0); + Assert.assertTrue(targetHwAddress[3] == (byte)0x0); + Assert.assertTrue(targetHwAddress[4] == (byte)0x0); + Assert.assertTrue(targetHwAddress[5] == (byte)0x0); + + Assert.assertTrue(senderProtocolAddress[0] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[1] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[2] == (byte)0x9); + Assert.assertTrue(senderProtocolAddress[3] == (byte)0x1); + + Assert.assertTrue(targetProtocolAddress[0] == (byte)0x9); + Assert.assertTrue(targetProtocolAddress[1] == (byte)0x9); + Assert.assertTrue(targetProtocolAddress[2] == (byte)0x9); + Assert.assertTrue(targetProtocolAddress[3] == (byte)0xFE); + } + + @Test + public void DataPacketServiceEncodeTest() throws ConstructionException, InstantiationException, IllegalAccessException { + + DataPacketService dService = new DataPacketService(); + Ethernet eth = new Ethernet(); + ARP arp = new ARP(); + + byte[] data = null; + RawPacket rawPkt; + + + byte[] dMAC = { 10, 12, 14, 20, 55, 69 }; + byte[] sMAC = { 82, 97, 109, 117, 127, -50 }; + short etherType = 2054; + + eth.setDestinationMACAddress(dMAC); + eth.setSourceMACAddress(sMAC); + eth.setEtherType(etherType); + + arp.setHardwareType((short)1); + arp.setProtocolType((short)2048); + arp.setHardwareAddressLength((byte)0x6); + arp.setProtocolAddressLength((byte)0x4); + arp.setOpCode((byte)0x1); + + byte[] senderHardwareAddress = {(byte)0xA6, (byte)0xEC, (byte)0x9C, (byte)0xAE, + (byte)0xB2, (byte)0x9F}; + byte[] senderProtocolAddress = {(byte)0x09, (byte)0x09, (byte)0x09, (byte)0x01}; + byte[] targetProtocolAddress = {(byte)0x09, (byte)0x09, (byte)0x09, (byte)0xFE}; + byte[] targetHardwareAddress = {(byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0}; + arp.setSenderHardwareAddress(senderHardwareAddress); + arp.setSenderProtocolAddress(senderProtocolAddress); + arp.setTargetHardwareAddress(targetHardwareAddress); + arp.setTargetProtocolAddress(targetProtocolAddress); + + arp.setParent(eth); + eth.setPayload(arp); + + rawPkt = dService.encodeDataPacket(eth); + data = rawPkt.getPacketData(); + + Assert.assertTrue(data[0] == (byte)0x0A);//Destination MAC + Assert.assertTrue(data[1] == (byte)0x0C); + Assert.assertTrue(data[2] == (byte)0x0E); + Assert.assertTrue(data[3] == (byte)0x14); + Assert.assertTrue(data[4] == (byte)0x37); + Assert.assertTrue(data[5] == (byte)0x45); + Assert.assertTrue(data[6] == (byte)0x52);//Source MAC + Assert.assertTrue(data[7] == (byte)0x61); + Assert.assertTrue(data[8] == (byte)0x6D); + Assert.assertTrue(data[9] == (byte)0x75); + Assert.assertTrue(data[10] == (byte)0x7F); + Assert.assertTrue(data[11] == (byte)0xCE); + Assert.assertTrue(data[12] == (byte)0x08);//EtherType + Assert.assertTrue(data[13] == (byte)0x06); + Assert.assertTrue(data[14] == (byte)0x00);//Hardware Type + Assert.assertTrue(data[15] == (byte)0x01); + Assert.assertTrue(data[16] == (byte)0x08);//Protocol Type + Assert.assertTrue(data[17] == (byte)0x0); + Assert.assertTrue(data[18] == (byte)0x6);//Hardware Address Length + Assert.assertTrue(data[19] == (byte)0x4);//Protocol Address Length + Assert.assertTrue(data[20] == (byte)0x0);//Opcode + Assert.assertTrue(data[21] == (byte)0x1);//Opcode + Assert.assertTrue(data[22] == (byte)0xA6);//Sender Hardware Address + Assert.assertTrue(data[23] == (byte)0xEC); + Assert.assertTrue(data[24] == (byte)0x9C); + Assert.assertTrue(data[25] == (byte)0xAE); + Assert.assertTrue(data[26] == (byte)0xB2); + Assert.assertTrue(data[27] == (byte)0x9F); + Assert.assertTrue(data[28] == (byte)0x09);//Sender Protocol Address + Assert.assertTrue(data[29] == (byte)0x09); + Assert.assertTrue(data[30] == (byte)0x09); + Assert.assertTrue(data[31] == (byte)0x01);//Target Hardware Address + Assert.assertTrue(data[32] == (byte)0x00); + Assert.assertTrue(data[33] == (byte)0x00); + Assert.assertTrue(data[34] == (byte)0x00); + Assert.assertTrue(data[35] == (byte)0x00); + Assert.assertTrue(data[36] == (byte)0x00); + Assert.assertTrue(data[37] == (byte)0x00); + Assert.assertTrue(data[38] == (byte)0x09);//Target Protocol Address + Assert.assertTrue(data[39] == (byte)0x09); + Assert.assertTrue(data[40] == (byte)0x09); + Assert.assertTrue(data[41] == (byte)0xFE); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/.gitignore b/opendaylight/sal/yang-prototype/code-generator/.gitignore new file mode 100644 index 0000000000..40a85ffb28 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/.gitignore @@ -0,0 +1 @@ +/.settings diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/pom.xml b/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/pom.xml new file mode 100644 index 0000000000..a45b6f321a --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + org.opendaylight.controller + binding-generator + 1.0 + + binding-generator-api + + + org.opendaylight.controller + binding-model-api + 1.0 + + + org.opendaylight.controller + sal-schema-repository-api + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/src/main/java/org/opendaylight/controller/sal/binding/generator/api/BindingGenerator.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/src/main/java/org/opendaylight/controller/sal/binding/generator/api/BindingGenerator.java new file mode 100644 index 0000000000..686f364132 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/src/main/java/org/opendaylight/controller/sal/binding/generator/api/BindingGenerator.java @@ -0,0 +1,19 @@ +/* + * 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.controller.sal.binding.generator.api; + +import java.util.List; + +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; +import org.opendaylight.controller.yang.model.api.Module; + +public interface BindingGenerator { + + public List generateTypes(final Module module); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/src/main/java/org/opendaylight/controller/sal/binding/generator/api/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/src/main/java/org/opendaylight/controller/sal/binding/generator/api/package-info.java new file mode 100644 index 0000000000..237690c423 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-api/src/main/java/org/opendaylight/controller/sal/binding/generator/api/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.binding.generator.api; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/pom.xml b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/pom.xml new file mode 100644 index 0000000000..9b178c09c9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/pom.xml @@ -0,0 +1,32 @@ + + 4.0.0 + + org.opendaylight.controller + binding-generator + 1.0 + + binding-generator-impl + + + org.opendaylight.controller + binding-generator-util + 1.0 + + + + org.opendaylight.controller + yang-model-parser-impl + 1.0 + + + org.opendaylight.controller + binding-generator-api + 1.0 + + + org.opendaylight.controller + binding-generator-spi + 1.0 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/BindingGeneratorImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/BindingGeneratorImpl.java new file mode 100644 index 0000000000..d346352350 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/BindingGeneratorImpl.java @@ -0,0 +1,420 @@ +/* + * 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.controller.sal.binding.generator.impl; + +import java.net.URI; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.binding.generator.util.CodeGeneratorHelper; +import org.opendaylight.controller.binding.generator.util.Types; +import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator; +import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider; +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder; +import org.opendaylight.controller.sal.binding.model.api.type.builder.MethodSignatureBuilder; +import org.opendaylight.controller.sal.binding.yang.types.TypeProviderImpl; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; +import org.opendaylight.controller.yang.model.api.DataNodeContainer; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.LeafListSchemaNode; +import org.opendaylight.controller.yang.model.api.LeafSchemaNode; +import org.opendaylight.controller.yang.model.api.ListSchemaNode; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public class BindingGeneratorImpl implements BindingGenerator { + + private static DateFormat simpleDateFormat = new SimpleDateFormat( + "yyyy-MM-dd"); + private static Calendar calendar = new GregorianCalendar(); + + private final Map> genTypeBuilders; + private final List schemaContainers; + private final List schemaLists; + + private final TypeProvider typeProvider; + + private String basePackageName; + + public BindingGeneratorImpl() { + super(); + genTypeBuilders = new HashMap>(); + schemaContainers = new ArrayList(); + schemaLists = new ArrayList(); + + // TODO: reimplement in better way + typeProvider = new TypeProviderImpl(); + } + + @Override + public List generateTypes(final Module module) { + final List genTypes = new ArrayList(); + + basePackageName = resolveBasePackageName(module.getNamespace(), + module.getYangVersion()); + + traverseModule(module); + if (schemaContainers.size() > 0) { + for (final ContainerSchemaNode container : schemaContainers) { + genTypes.add(containerToGenType(container)); + } + } + + if (schemaLists.size() > 0) { + for (final ListSchemaNode list : schemaLists) { + genTypes.add(listToGenType(list)); + } + } + + return genTypes; + } + + private String resolveGeneratedTypePackageName(final SchemaPath schemaPath) { + final StringBuilder builder = new StringBuilder(); + builder.append(basePackageName); + if ((schemaPath != null) && (schemaPath.getPath() != null)) { + final List pathToNode = schemaPath.getPath(); + for (int i = 0; i < pathToNode.size(); ++i) { + builder.append("."); + String nodeLocalName = pathToNode.get(i).getLocalName(); + + // TODO: create method + nodeLocalName = nodeLocalName.replace(":", "."); + nodeLocalName = nodeLocalName.replace("-", "."); + builder.append(nodeLocalName); + } + return builder.toString(); + } + return null; + } + + private GeneratedType containerToGenType(ContainerSchemaNode container) { + if (container == null) { + return null; + } + final Set schemaNodes = container.getChildNodes(); + final GeneratedTypeBuilder typeBuilder = addRawInterfaceDefinition(container); + + for (final DataSchemaNode node : schemaNodes) { + if (node instanceof LeafSchemaNode) { + resolveLeafSchemaNode(typeBuilder, (LeafSchemaNode) node); + } else if (node instanceof LeafListSchemaNode) { + resolveLeafListSchemaNode(typeBuilder, + (LeafListSchemaNode) node); + + } else if (node instanceof ContainerSchemaNode) { + resolveContainerSchemaNode(typeBuilder, + (ContainerSchemaNode) node); + } else if (node instanceof ListSchemaNode) { + resolveListSchemaNode(typeBuilder, (ListSchemaNode) node); + } + } + return typeBuilder.toInstance(); + } + + private boolean resolveLeafSchemaNode( + final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode node) { + if ((node != null) && (typeBuilder != null)) { + final String nodeName = node.getQName().getLocalName(); + String nodeDesc = node.getDescription(); + if (nodeDesc == null) { + nodeDesc = ""; + } + + if (nodeName != null) { + final TypeDefinition typeDef = node.getType(); + final Type javaType = typeProvider + .javaTypeForSchemaDefinitionType(typeDef); + + constructGetter(typeBuilder, nodeName, nodeDesc, javaType); + if (!node.isConfiguration()) { + constructSetter(typeBuilder, nodeName, nodeDesc, javaType); + } + return true; + } + } + return false; + } + + private boolean resolveLeafListSchemaNode( + final GeneratedTypeBuilder typeBuilder, + final LeafListSchemaNode node) { + if ((node != null) && (typeBuilder != null)) { + final String nodeName = node.getQName().getLocalName(); + String nodeDesc = node.getDescription(); + if (nodeDesc == null) { + nodeDesc = ""; + } + + if (nodeName != null) { + final TypeDefinition type = node.getType(); + final Type listType = Types.listTypeFor(typeProvider + .javaTypeForSchemaDefinitionType(type)); + + constructGetter(typeBuilder, nodeName, nodeDesc, listType); + if (!node.isConfiguration()) { + constructSetter(typeBuilder, nodeName, nodeDesc, listType); + } + return true; + } + } + return false; + } + + private boolean resolveContainerSchemaNode( + final GeneratedTypeBuilder typeBuilder, + final ContainerSchemaNode node) { + if ((node != null) && (typeBuilder != null)) { + final String nodeName = node.getQName().getLocalName(); + + if (nodeName != null) { + final GeneratedTypeBuilder rawGenType = addRawInterfaceDefinition(node); + constructGetter(typeBuilder, nodeName, "", rawGenType); + + return true; + } + } + return false; + } + + private boolean resolveListSchemaNode( + final GeneratedTypeBuilder typeBuilder, final ListSchemaNode node) { + if ((node != null) && (typeBuilder != null)) { + final String nodeName = node.getQName().getLocalName(); + + if (nodeName != null) { + final GeneratedTypeBuilder rawGenType = addRawInterfaceDefinition(node); + constructGetter(typeBuilder, nodeName, "", + Types.listTypeFor(rawGenType)); + if (!node.isConfiguration()) { + constructSetter(typeBuilder, nodeName, "", + Types.listTypeFor(rawGenType)); + } + return true; + } + } + return false; + } + + private GeneratedTypeBuilder addRawInterfaceDefinition( + final DataSchemaNode schemaNode) { + if (schemaNode == null) { + return null; + } + + final String packageName = resolveGeneratedTypePackageName(schemaNode + .getPath()); + final String schemaNodeName = schemaNode.getQName().getLocalName(); + + if ((packageName != null) && (schemaNode != null) + && (schemaNodeName != null)) { + final String genTypeName = CodeGeneratorHelper + .parseToClassName(schemaNodeName); + final GeneratedTypeBuilder newType = new GeneratedTypeBuilderImpl( + packageName, genTypeName); + + if (!genTypeBuilders.containsKey(packageName)) { + final Map builders = new HashMap(); + builders.put(genTypeName, newType); + genTypeBuilders.put(packageName, builders); + } else { + final Map builders = genTypeBuilders + .get(packageName); + if (!builders.containsKey(genTypeName)) { + builders.put(genTypeName, newType); + } + } + + return newType; + } + return null; + } + + private String getterMethodName(final String methodName) { + final StringBuilder method = new StringBuilder(); + method.append("get"); + method.append(CodeGeneratorHelper.parseToClassName(methodName)); + return method.toString(); + } + + private String setterMethodName(final String methodName) { + final StringBuilder method = new StringBuilder(); + method.append("set"); + method.append(CodeGeneratorHelper.parseToClassName(methodName)); + return method.toString(); + } + + private MethodSignatureBuilder constructGetter( + final GeneratedTypeBuilder interfaceBuilder, + final String schemaNodeName, final String comment, + final Type returnType) { + final MethodSignatureBuilder getMethod = interfaceBuilder + .addMethod(getterMethodName(schemaNodeName)); + + getMethod.addComment(comment); + getMethod.addReturnType(returnType); + + return getMethod; + } + + private MethodSignatureBuilder constructSetter( + final GeneratedTypeBuilder interfaceBuilder, + final String schemaNodeName, final String comment, + final Type parameterType) { + final MethodSignatureBuilder setMethod = interfaceBuilder + .addMethod(setterMethodName(schemaNodeName)); + + setMethod.addComment(comment); + setMethod.addParameter(parameterType, + CodeGeneratorHelper.parseToParamName(schemaNodeName)); + setMethod.addReturnType(Types.voidType()); + + return setMethod; + } + + private boolean isCompositeKey(final String keyDefinition) { + if (keyDefinition.contains(" ")) { + return true; + } + return false; + } + + private String resolveBasePackageName(final URI moduleNamespace, + final String yangVersion) { + final StringBuilder packageNameBuilder = new StringBuilder(); + + packageNameBuilder.append("com.cisco.yang.gen.v"); + packageNameBuilder.append(yangVersion); + packageNameBuilder.append(".rev"); + packageNameBuilder.append(calendar.get(Calendar.YEAR)); + packageNameBuilder.append((calendar.get(Calendar.MONTH) + 1)); + packageNameBuilder.append(calendar.get(Calendar.DAY_OF_MONTH)); + packageNameBuilder.append("."); + + String namespace = moduleNamespace.toString(); + namespace = namespace.replace(":", "."); + namespace = namespace.replace("-", "."); + + packageNameBuilder.append(namespace); + + return packageNameBuilder.toString(); + } + + private GeneratedType listToGenType(ListSchemaNode list) { + if (list == null) { + return null; + } + final GeneratedTypeBuilder typeBuilder = resolveListTypeBuilder(list); + + final Set schemaNodes = list.getChildNodes(); + for (final DataSchemaNode node : schemaNodes) { + if (node instanceof LeafSchemaNode) { + resolveLeafSchemaNode(typeBuilder, (LeafSchemaNode) node); + } else if (node instanceof LeafListSchemaNode) { + resolveLeafListSchemaNode(typeBuilder, + (LeafListSchemaNode) node); + } else if (node instanceof ContainerSchemaNode) { + resolveContainerSchemaNode(typeBuilder, + (ContainerSchemaNode) node); + } else if (node instanceof ListSchemaNode) { + resolveListSchemaNode(typeBuilder, (ListSchemaNode) node); + } + } + return typeBuilder.toInstance(); + } + + private GeneratedTypeBuilder resolveListTypeBuilder( + final ListSchemaNode list) { + final String packageName = resolveGeneratedTypePackageName(list + .getPath()); + final String schemaNodeName = list.getQName().getLocalName(); + final String genTypeName = CodeGeneratorHelper + .parseToClassName(schemaNodeName); + + GeneratedTypeBuilder typeBuilder = null; + if (genTypeBuilders.containsKey(packageName)) { + final Map builders = new HashMap(); + typeBuilder = builders.get(genTypeName); + + if (null == typeBuilder) { + typeBuilder = addRawInterfaceDefinition(list); + } + } + return typeBuilder; + } + + private void traverseModule(final Module module) { + final Set schemaNodes = module.getChildNodes(); + + for (DataSchemaNode node : schemaNodes) { + if (node instanceof ContainerSchemaNode) { + schemaContainers.add((ContainerSchemaNode) node); + traverse((ContainerSchemaNode) node); + } + } + } + + private void traverse(final DataNodeContainer dataNode) { + if (!containChildDataNodeContainer(dataNode)) { + return; + } + + final Set childs = dataNode.getChildNodes(); + if (childs != null) { + for (DataSchemaNode childNode : childs) { + if (childNode instanceof ContainerSchemaNode) { + final ContainerSchemaNode container = (ContainerSchemaNode) childNode; + schemaContainers.add(container); + traverse(container); + } + + if (childNode instanceof ListSchemaNode) { + final ListSchemaNode list = (ListSchemaNode) childNode; + schemaLists.add(list); + traverse(list); + } + } + } + } + + /** + * Returns true if and only if the child node contain at least + * one child container schema node or child list schema node, otherwise will + * always returns false + * + * @param container + * @return true if and only if the child node contain at least + * one child container schema node or child list schema node, + * otherwise will always returns false + */ + private boolean containChildDataNodeContainer( + final DataNodeContainer container) { + if (container != null) { + final Set childs = container.getChildNodes(); + if ((childs != null) && (childs.size() > 0)) { + for (final DataSchemaNode childNode : childs) { + if (childNode instanceof DataNodeContainer) { + return true; + } + } + } + } + return false; + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/ConstantBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/ConstantBuilderImpl.java new file mode 100644 index 0000000000..cb2fc872b9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/ConstantBuilderImpl.java @@ -0,0 +1,189 @@ +/* + * 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.controller.sal.binding.generator.impl; + +import org.opendaylight.controller.sal.binding.model.api.Constant; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.sal.binding.model.api.type.builder.ConstantBuilder; + +final class ConstantBuilderImpl implements ConstantBuilder { + + private final Type type; + private final String name; + private Object value; + + public ConstantBuilderImpl(Type type, String name, Object value) { + super(); + this.type = type; + this.name = name; + this.value = value; + } + + public ConstantBuilderImpl(Type type, String name) { + super(); + this.type = type; + this.name = name; + } + + @Override + public void assignValue(Object value) { + this.value = value; + } + + @Override + public Constant toInstance(final Type definingType) { + return new ConstantImpl(definingType, type, name, value); + } + + private static final class ConstantImpl implements Constant { + + final Type definingType; + private final Type type; + private final String name; + private final Object value; + + public ConstantImpl(final Type definingType, final Type type, + final String name, final Object value) { + super(); + this.definingType = definingType; + this.type = type; + this.name = name; + this.value = value; + } + + @Override + public Type getDefiningType() { + return definingType; + } + + @Override + public Type getType() { + return type; + } + + @Override + public String getName() { + return name; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public String toFormattedString() { + StringBuilder builder = new StringBuilder(); + builder.append(type); + builder.append(" "); + builder.append(name); + builder.append(" "); + builder.append(value); + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + if (definingType != null) { + result = prime + * result + + ((definingType.getPackageName() == null) ? 0 + : definingType.getPackageName().hashCode()); + result = prime + * result + + ((definingType.getName() == null) ? 0 : definingType + .getName().hashCode()); + } + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ConstantImpl other = (ConstantImpl) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (type == null) { + if (other.type != null) { + return false; + } + } else if (!type.equals(other.type)) { + return false; + } + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + if (definingType == null) { + if (other.definingType != null) { + return false; + } + } else if ((definingType != null) && (other.definingType != null)) { + if (!definingType.getPackageName().equals( + other.definingType.getPackageName()) + && !definingType.getName().equals( + other.definingType.getName())) { + return false; + } + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ConstantImpl [type="); + builder.append(type); + builder.append(", name="); + builder.append(name); + builder.append(", value="); + builder.append(value); + if (definingType != null) { + builder.append(", definingType="); + builder.append(definingType.getPackageName()); + builder.append("."); + builder.append(definingType.getName()); + } else { + builder.append(", definingType= null"); + } + builder.append("]"); + return builder.toString(); + } + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/EnumerationBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/EnumerationBuilderImpl.java new file mode 100644 index 0000000000..6eadb766f4 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/EnumerationBuilderImpl.java @@ -0,0 +1,365 @@ +/* + * 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.controller.sal.binding.generator.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.sal.binding.model.api.Enumeration; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.sal.binding.model.api.type.builder.EnumBuilder; + +final class EnumerationBuilderImpl implements EnumBuilder { + private final String packageName; + private final String name; + private final List values; + + public EnumerationBuilderImpl(final String packageName, final String name) { + super(); + this.packageName = packageName; + this.name = name; + values = new ArrayList(); + } + + @Override + public void addValue(final String name, final Integer value) { + values.add(new EnumPairImpl(name, value)); + } + + @Override + public Enumeration toInstance(final Type definingType) { + return new EnumerationImpl(definingType, packageName, name, values); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((packageName == null) ? 0 : packageName.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + EnumerationBuilderImpl other = (EnumerationBuilderImpl) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (packageName == null) { + if (other.packageName != null) { + return false; + } + } else if (!packageName.equals(other.packageName)) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("EnumerationBuilderImpl [packageName="); + builder.append(packageName); + builder.append(", name="); + builder.append(name); + builder.append(", values="); + builder.append(values); + builder.append("]"); + return builder.toString(); + } + + private static final class EnumPairImpl implements Enumeration.Pair { + + private final String name; + private final Integer value; + + public EnumPairImpl(String name, Integer value) { + super(); + this.name = name; + this.value = value; + } + + @Override + public String getName() { + return name; + } + + @Override + public Integer getValue() { + return value; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + EnumPairImpl other = (EnumPairImpl) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("EnumPairImpl [name="); + builder.append(name); + builder.append(", value="); + builder.append(value); + builder.append("]"); + return builder.toString(); + } + } + + private static final class EnumerationImpl implements Enumeration { + + private final Type definingType; + private final String packageName; + private final String name; + private final List values; + + public EnumerationImpl(final Type definingType, + final String packageName, final String name, + final List values) { + super(); + this.definingType = definingType; + this.packageName = packageName; + this.name = name; + this.values = Collections.unmodifiableList(values); + } + + @Override + public Type getDefiningType() { + return definingType; + } + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public String getName() { + return name; + } + + @Override + public List getValues() { + return values; + } + + @Override + public String toFormattedString() { + StringBuilder builder = new StringBuilder(); + builder.append("public enum"); + builder.append(" "); + builder.append(name); + builder.append(" {"); + builder.append("\n"); + + int i = 0; + for (final Enumeration.Pair valPair : values) { + builder.append("\t"); + builder.append(" "); + builder.append(valPair.getName()); + builder.append(" ("); + builder.append(valPair.getValue()); + + if (i == (values.size() - 1)) { + builder.append(" );"); + } else { + builder.append(" ),"); + } + ++i; + } + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((packageName == null) ? 0 : packageName.hashCode()); + result = prime * result + + ((values == null) ? 0 : values.hashCode()); + + if (definingType != null) { + result = prime + * result + + ((definingType.getPackageName() == null) ? 0 + : definingType.getPackageName().hashCode()); + result = prime + * result + + ((definingType.getName() == null) ? 0 : definingType + .getName().hashCode()); + } + + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + EnumerationImpl other = (EnumerationImpl) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (packageName == null) { + if (other.packageName != null) { + return false; + } + } else if (!packageName.equals(other.packageName)) { + return false; + } + if (values == null) { + if (other.values != null) { + return false; + } + } else if (!values.equals(other.values)) { + return false; + } + if (definingType == null) { + if (other.definingType != null) { + return false; + } + } else if ((definingType != null) && (other.definingType != null)) { + if (!definingType.getPackageName().equals( + other.definingType.getPackageName()) + && !definingType.getName().equals( + other.definingType.getName())) { + return false; + } + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("EnumerationImpl [packageName="); + builder.append(packageName); + if (definingType != null) { + builder.append(", definingType="); + builder.append(definingType.getPackageName()); + builder.append("."); + builder.append(definingType.getName()); + } else { + builder.append(", definingType= null"); + } + builder.append(", name="); + builder.append(name); + builder.append(", values="); + builder.append(values); + builder.append("]"); + return builder.toString(); + } + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/GeneratedTOBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/GeneratedTOBuilderImpl.java new file mode 100644 index 0000000000..90b2ebfc63 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/GeneratedTOBuilderImpl.java @@ -0,0 +1,560 @@ +/* + * 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.controller.sal.binding.generator.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.sal.binding.model.api.AccessModifier; +import org.opendaylight.controller.sal.binding.model.api.Constant; +import org.opendaylight.controller.sal.binding.model.api.Enumeration; +import org.opendaylight.controller.sal.binding.model.api.GeneratedProperty; +import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject; +import org.opendaylight.controller.sal.binding.model.api.MethodSignature; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.sal.binding.model.api.type.builder.ConstantBuilder; +import org.opendaylight.controller.sal.binding.model.api.type.builder.EnumBuilder; +import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedPropertyBuilder; +import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTOBuilder; + +final class GeneratedTOBuilderImpl implements GeneratedTOBuilder { + + private final String packageName; + private final String name; + + private final List enumerations = new ArrayList(); + private final List properties = new ArrayList(); + private final List equalsProperties = new ArrayList(); + private final List hashProperties = new ArrayList(); + private final List toStringProperties = new ArrayList(); + + public GeneratedTOBuilderImpl(String packageName, String name) { + super(); + this.packageName = packageName; + this.name = name; + } + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public String getName() { + return name; + } + + @Override + public EnumBuilder addEnumeration(String name) { + final EnumBuilder builder = new EnumerationBuilderImpl(packageName, + name); + enumerations.add(builder); + return builder; + } + + @Override + public GeneratedPropertyBuilder addProperty(String name) { + final GeneratedPropertyBuilder builder = new GeneratedPropertyBuilderImpl( + name); + properties.add(builder); + return builder; + } + + @Override + public boolean addEqualsIdentity(GeneratedPropertyBuilder property) { + return equalsProperties.add(property); + } + + @Override + public boolean addHashIdentity(GeneratedPropertyBuilder property) { + return hashProperties.add(property); + } + + @Override + public boolean addToStringProperty(GeneratedPropertyBuilder property) { + return toStringProperties.add(property); + } + + @Override + public GeneratedTransferObject toInstance() { + return new GeneratedTransferObjectImpl(packageName, name, enumerations, + properties, equalsProperties, hashProperties, + toStringProperties); + } + + private static final class GeneratedPropertyBuilderImpl implements + GeneratedPropertyBuilder { + + private final String name; + private Type returnType; + private final List parameters; + private String comment = ""; + private AccessModifier accessModifier; + private boolean isFinal; + private boolean isReadOnly; + + public GeneratedPropertyBuilderImpl(final String name) { + super(); + this.name = name; + parameters = new ArrayList(); + isFinal = true; + this.isReadOnly = true; + accessModifier = AccessModifier.PUBLIC; + } + + public String getName() { + return name; + } + + @Override + public boolean addReturnType(Type returnType) { + if (returnType != null) { + this.returnType = returnType; + this.parameters.add(new MethodParameterImpl(name, returnType)); + return true; + } + return false; + } + + @Override + public void accessorModifier(final AccessModifier modifier) { + accessModifier = modifier; + } + + @Override + public void addComment(String comment) { + if (comment != null) { + this.comment = comment; + } + } + + @Override + public void setFinal(boolean isFinal) { + this.isFinal = isFinal; + } + + @Override + public void setReadOnly(boolean isReadOnly) { + this.isReadOnly = isReadOnly; + } + + @Override + public GeneratedProperty toInstance(final Type definingType) { + return new GeneratedPropertyImpl(name, comment, definingType, + returnType, isFinal, isReadOnly, parameters, accessModifier); + } + } + + private static final class GeneratedPropertyImpl implements + GeneratedProperty { + + private final String name; + private final String comment; + private final Type parent; + private final Type returnType; + private final boolean isFinal; + private final boolean isReadOnly; + private final List parameters; + private final AccessModifier modifier; + + public GeneratedPropertyImpl(final String name, final String comment, + final Type parent, final Type returnType, + final boolean isFinal, final boolean isReadOnly, + final List parameters, final AccessModifier modifier) { + super(); + this.name = name; + this.comment = comment; + this.parent = parent; + this.returnType = returnType; + this.isFinal = isFinal; + this.isReadOnly = isReadOnly; + this.parameters = Collections.unmodifiableList(parameters); + this.modifier = modifier; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getComment() { + return comment; + } + + @Override + public Type getDefiningType() { + return parent; + } + + @Override + public Type getReturnType() { + return returnType; + } + + @Override + public List getParameters() { + return parameters; + } + + @Override + public AccessModifier getAccessModifier() { + return modifier; + } + + @Override + public boolean isReadOnly() { + return isReadOnly; + } + + @Override + public boolean isFinal() { + return isFinal; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((comment == null) ? 0 : comment.hashCode()); + result = prime * result + (isFinal ? 1231 : 1237); + result = prime * result + (isReadOnly ? 1231 : 1237); + result = prime * result + + ((modifier == null) ? 0 : modifier.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((parameters == null) ? 0 : parameters.hashCode()); + + if (parent != null) { + result = prime + * result + + ((parent.getPackageName() == null) ? 0 : parent + .getPackageName().hashCode()); + result = prime + * result + + ((parent.getName() == null) ? 0 : parent.getName() + .hashCode()); + } + + result = prime * result + + ((returnType == null) ? 0 : returnType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + GeneratedPropertyImpl other = (GeneratedPropertyImpl) obj; + if (comment == null) { + if (other.comment != null) { + return false; + } + } else if (!comment.equals(other.comment)) { + return false; + } + if (isFinal != other.isFinal) { + return false; + } + if (isReadOnly != other.isReadOnly) { + return false; + } + if (modifier != other.modifier) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (parameters == null) { + if (other.parameters != null) { + return false; + } + } else if (!parameters.equals(other.parameters)) { + return false; + } + if (parent == null) { + if (other.parent != null) { + return false; + } + } else if ((parent != null) && (other.parent != null)) { + if (!parent.getPackageName().equals( + other.parent.getPackageName()) + && !parent.getName().equals(other.parent.getName())) { + return false; + } + } + if (returnType == null) { + if (other.returnType != null) { + return false; + } + } else if (!returnType.equals(other.returnType)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GeneratedPropertyImpl [name="); + builder.append(name); + builder.append(", comment="); + builder.append(comment); + if (parent != null) { + builder.append(", parent="); + builder.append(parent.getPackageName()); + builder.append("."); + builder.append(parent.getName()); + } else { + builder.append(", parent= null"); + } + builder.append(", returnType="); + builder.append(returnType); + builder.append(", isFinal="); + builder.append(isFinal); + builder.append(", isReadOnly="); + builder.append(isReadOnly); + builder.append(", parameters="); + builder.append(parameters); + builder.append(", modifier="); + builder.append(modifier); + builder.append("]"); + return builder.toString(); + } + } + + private static final class GeneratedTransferObjectImpl implements + GeneratedTransferObject { + + private final String packageName; + private final String name; + // private final List constants; + private final List enumerations; + private final List properties; + private final List equalsProperties; + private final List hashCodeProperties; + private final List stringProperties; + + private List toUnmodifiableEnumerations( + final List enumBuilders) { + final List enumerations = new ArrayList(); + for (final EnumBuilder builder : enumBuilders) { + enumerations.add(builder.toInstance(this)); + } + return Collections.unmodifiableList(enumerations); + } + + private List toUnmodifiableConstant( + final List constBuilders) { + final List constants = new ArrayList(); + for (final ConstantBuilder builder : constBuilders) { + constants.add(builder.toInstance(this)); + } + return Collections.unmodifiableList(constants); + } + + private List toUnmodifiableProperties( + final List propBuilders) { + final List constants = new ArrayList(); + for (final GeneratedPropertyBuilder builder : propBuilders) { + constants.add(builder.toInstance(this)); + } + return Collections.unmodifiableList(constants); + } + + public GeneratedTransferObjectImpl(String packageName, String name, + List enumBuilders, + List propBuilers, + List equalsBuilers, + List hashCodeBuilers, + List stringBuilers) { + super(); + this.packageName = packageName; + this.name = name; + this.enumerations = toUnmodifiableEnumerations(enumBuilders); + this.properties = toUnmodifiableProperties(propBuilers); + this.equalsProperties = toUnmodifiableProperties(equalsBuilers); + this.hashCodeProperties = toUnmodifiableProperties(hashCodeBuilers); + this.stringProperties = toUnmodifiableProperties(stringBuilers); + } + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public String getName() { + return name; + } + + @Override + public List getEnumDefintions() { + return enumerations; + } + + @Override + public List getProperties() { + return properties; + } + + @Override + public List getEqualsIdentifiers() { + return equalsProperties; + } + + @Override + public List getHashCodeIdentifiers() { + return hashCodeProperties; + } + + @Override + public List getToStringIdentifiers() { + return stringProperties; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((enumerations == null) ? 0 : enumerations.hashCode()); + result = prime + * result + + ((equalsProperties == null) ? 0 : equalsProperties + .hashCode()); + result = prime + * result + + ((hashCodeProperties == null) ? 0 : hashCodeProperties + .hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((packageName == null) ? 0 : packageName.hashCode()); + result = prime * result + + ((properties == null) ? 0 : properties.hashCode()); + result = prime + * result + + ((stringProperties == null) ? 0 : stringProperties + .hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + GeneratedTransferObjectImpl other = (GeneratedTransferObjectImpl) obj; + if (enumerations == null) { + if (other.enumerations != null) { + return false; + } + } else if (!enumerations.equals(other.enumerations)) { + return false; + } + if (equalsProperties == null) { + if (other.equalsProperties != null) { + return false; + } + } else if (!equalsProperties.equals(other.equalsProperties)) { + return false; + } + if (hashCodeProperties == null) { + if (other.hashCodeProperties != null) { + return false; + } + } else if (!hashCodeProperties.equals(other.hashCodeProperties)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (packageName == null) { + if (other.packageName != null) { + return false; + } + } else if (!packageName.equals(other.packageName)) { + return false; + } + if (properties == null) { + if (other.properties != null) { + return false; + } + } else if (!properties.equals(other.properties)) { + return false; + } + if (stringProperties == null) { + if (other.stringProperties != null) { + return false; + } + } else if (!stringProperties.equals(other.stringProperties)) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GeneratedTransferObjectImpl [packageName="); + builder.append(packageName); + builder.append(", name="); + builder.append(name); + builder.append(", enumerations="); + builder.append(enumerations); + builder.append(", properties="); + builder.append(properties); + builder.append(", equalsProperties="); + builder.append(equalsProperties); + builder.append(", hashCodeProperties="); + builder.append(hashCodeProperties); + builder.append(", stringProperties="); + builder.append(stringProperties); + builder.append("]"); + return builder.toString(); + } + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/GeneratedTypeBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/GeneratedTypeBuilderImpl.java new file mode 100644 index 0000000000..c861b54591 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/GeneratedTypeBuilderImpl.java @@ -0,0 +1,503 @@ +/* + * 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.controller.sal.binding.generator.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.sal.binding.model.api.AccessModifier; +import org.opendaylight.controller.sal.binding.model.api.Constant; +import org.opendaylight.controller.sal.binding.model.api.Enumeration; +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; +import org.opendaylight.controller.sal.binding.model.api.MethodSignature; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.sal.binding.model.api.type.builder.ConstantBuilder; +import org.opendaylight.controller.sal.binding.model.api.type.builder.EnumBuilder; +import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder; +import org.opendaylight.controller.sal.binding.model.api.type.builder.MethodSignatureBuilder; + +public final class GeneratedTypeBuilderImpl implements GeneratedTypeBuilder { + + private final String packageName; + private String comment; + private final String name; + private final List enumDefinitions = new ArrayList(); + private final List constantDefintions = new ArrayList(); + private final List methodDefinitions = new ArrayList(); + + public GeneratedTypeBuilderImpl(final String packageName, final String name) { + this.packageName = packageName; + this.name = name; + } + + @Override + public Type getParentType() { + return this; + } + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public String getName() { + return name; + } + + @Override + public void addComment(String comment) { + this.comment = comment; + } + + @Override + public ConstantBuilder addConstant(Type type, String name, Object value) { + final ConstantBuilder builder = new ConstantBuilderImpl(type, name, + value); + constantDefintions.add(builder); + + return builder; + } + + @Override + public EnumBuilder addEnumeration(final String name) { + final EnumBuilder builder = new EnumerationBuilderImpl(packageName, + name); + enumDefinitions.add(builder); + return builder; + } + + @Override + public MethodSignatureBuilder addMethod(final String name) { + final MethodSignatureBuilder builder = new MethodSignatureBuilderImpl( + this, name); + methodDefinitions.add(builder); + return builder; + } + + @Override + public GeneratedType toInstance() { + return new GeneratedTypeImpl(this, packageName, name, enumDefinitions, + constantDefintions, methodDefinitions); + } + + private static final class MethodSignatureBuilderImpl implements + MethodSignatureBuilder { + + private final String name; + private Type returnType; + private final List parameters; + private String comment = ""; + private final Type parent; + + public MethodSignatureBuilderImpl(final Type parent, final String name) { + super(); + this.name = name; + this.parent = parent; + parameters = new ArrayList(); + } + + @Override + public void addReturnType(Type returnType) { + if (returnType != null) { + this.returnType = returnType; + } + } + + @Override + public void addParameter(Type type, String name) { + parameters.add(new MethodParameterImpl(name, type)); + } + + @Override + public void addComment(String comment) { + this.comment = comment; + } + + @Override + public MethodSignature toInstance(Type definingType) { + return new MethodSignatureImpl(definingType, name, comment, + returnType, parameters); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MethodSignatureBuilderImpl other = (MethodSignatureBuilderImpl) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("MethodBuilderImpl [name="); + builder.append(name); + builder.append(", returnType="); + builder.append(returnType); + builder.append(", parameters="); + builder.append(parameters); + builder.append(", comment="); + builder.append(comment); + builder.append(", parent="); + builder.append(parent.getName()); + builder.append("]"); + return builder.toString(); + } + + } + + private static final class MethodSignatureImpl implements MethodSignature { + + private final String name; + private final String comment; + private final Type definingType; + private final Type returnType; + private final List params; + + public MethodSignatureImpl(final Type definingType, final String name, + final String comment, final Type returnType, + final List params) { + super(); + this.name = name; + this.comment = comment; + this.definingType = definingType; + this.returnType = returnType; + this.params = Collections.unmodifiableList(params); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getComment() { + return comment; + } + + @Override + public Type getDefiningType() { + return definingType; + } + + @Override + public Type getReturnType() { + return returnType; + } + + @Override + public List getParameters() { + return params; + } + + @Override + public AccessModifier getAccessModifier() { + return AccessModifier.PUBLIC; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((comment == null) ? 0 : comment.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((params == null) ? 0 : params.hashCode()); + result = prime * result + + ((returnType == null) ? 0 : returnType.hashCode()); + + if (definingType != null) { + result = prime + * result + + ((definingType.getPackageName() == null) ? 0 + : definingType.getPackageName().hashCode()); + result = prime + * result + + ((definingType.getName() == null) ? 0 : definingType + .getName().hashCode()); + } + + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MethodSignatureImpl other = (MethodSignatureImpl) obj; + if (comment == null) { + if (other.comment != null) { + return false; + } + } else if (!comment.equals(other.comment)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (params == null) { + if (other.params != null) { + return false; + } + } else if (!params.equals(other.params)) { + return false; + } + if (definingType == null) { + if (other.definingType != null) { + return false; + } + } else if ((definingType != null) && (other.definingType != null)) { + if (!definingType.getPackageName().equals( + other.definingType.getPackageName()) + && !definingType.getName().equals( + other.definingType.getName())) { + return false; + } + } + if (returnType == null) { + if (other.returnType != null) { + return false; + } + } else if (!returnType.equals(other.returnType)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("MethodImpl [name="); + builder.append(name); + builder.append(", comment="); + builder.append(comment); + if (definingType != null) { + builder.append(", definingType="); + builder.append(definingType.getPackageName()); + builder.append("."); + builder.append(definingType.getName()); + } else { + builder.append(", definingType= null"); + } + builder.append(", returnType="); + builder.append(returnType); + builder.append(", params="); + builder.append(params); + builder.append("]"); + return builder.toString(); + } + } + + private static final class GeneratedTypeImpl implements GeneratedType { + + private final Type parent; + private final String packageName; + private final String name; + private final List enumDefinitions; + private final List constantDefintions; + private final List methodDefinitions; + + public GeneratedTypeImpl(final Type parent, final String packageName, + final String name, final List enumBuilders, + final List constantBuilders, + final List methodBuilders) { + super(); + this.parent = parent; + this.packageName = packageName; + this.name = name; + + this.constantDefintions = toUnmodifiableConstants(constantBuilders); + this.enumDefinitions = toUnmodifiableEnums(enumBuilders); + this.methodDefinitions = toUnmodifiableMethods(methodBuilders); + } + + private List toUnmodifiableMethods( + List methodBuilders) { + final List methods = new ArrayList(); + for (final MethodSignatureBuilder methodBuilder : methodBuilders) { + methods.add(methodBuilder.toInstance(this)); + } + return Collections.unmodifiableList(methods); + } + + private List toUnmodifiableEnums( + List enumBuilders) { + final List enums = new ArrayList(); + for (final EnumBuilder enumBuilder : enumBuilders) { + enums.add(enumBuilder.toInstance(this)); + } + return Collections.unmodifiableList(enums); + } + + private List toUnmodifiableConstants( + List constantBuilders) { + final List constants = new ArrayList(); + for (final ConstantBuilder enumBuilder : constantBuilders) { + constants.add(enumBuilder.toInstance(this)); + } + return Collections.unmodifiableList(constants); + } + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public String getName() { + return name; + } + + @Override + public Type getParentType() { + return parent; + } + + @Override + public List getEnumDefintions() { + return enumDefinitions; + } + + @Override + public List getConstantDefinitions() { + return constantDefintions; + } + + @Override + public List getMethodDefinitions() { + return methodDefinitions; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime + * result + + ((constantDefintions == null) ? 0 : constantDefintions + .hashCode()); + result = prime + * result + + ((enumDefinitions == null) ? 0 : enumDefinitions + .hashCode()); + result = prime + * result + + ((methodDefinitions == null) ? 0 : methodDefinitions + .hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((packageName == null) ? 0 : packageName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + GeneratedTypeImpl other = (GeneratedTypeImpl) obj; + if (constantDefintions == null) { + if (other.constantDefintions != null) { + return false; + } + } else if (!constantDefintions.equals(other.constantDefintions)) { + return false; + } + if (enumDefinitions == null) { + if (other.enumDefinitions != null) { + return false; + } + } else if (!enumDefinitions.equals(other.enumDefinitions)) { + return false; + } + if (methodDefinitions == null) { + if (other.methodDefinitions != null) { + return false; + } + } else if (!methodDefinitions.equals(other.methodDefinitions)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (packageName == null) { + if (other.packageName != null) { + return false; + } + } else if (!packageName.equals(other.packageName)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("GeneratedTypeImpl [parent="); + builder.append(parent.getName()); + builder.append(", packageName="); + builder.append(packageName); + builder.append(", name="); + builder.append(name); + builder.append(", enumDefinitions="); + builder.append(enumDefinitions); + builder.append(", constantDefintions="); + builder.append(constantDefintions); + builder.append(", methodDefinitions="); + builder.append(methodDefinitions); + builder.append("]"); + return builder.toString(); + } + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/MethodParameterImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/MethodParameterImpl.java new file mode 100644 index 0000000000..08eab6007a --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/MethodParameterImpl.java @@ -0,0 +1,99 @@ +/* + * 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.controller.sal.binding.generator.impl; + +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.sal.binding.model.api.MethodSignature.Parameter; + +final class MethodParameterImpl implements Parameter { + + private final String name; + private final Type type; + + public MethodParameterImpl(final String name, final Type type) { + super(); + this.name = name; + this.type = type; + } + + @Override + public String getName() { + return name; + } + + @Override + public Type getType() { + return type; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MethodParameterImpl other = (MethodParameterImpl) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (type == null) { + if (other.type != null) { + return false; + } + } else if (!type.equals(other.type)) { + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("MethodParameterImpl [name="); + builder.append(name); + builder.append(", type="); + builder.append(type.getPackageName()); + builder.append("."); + builder.append(type.getName()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/package-info.java new file mode 100644 index 0000000000..741aeefd11 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.binding.generator.impl; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/BaseYangTypes.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/BaseYangTypes.java new file mode 100644 index 0000000000..d00b73d676 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/BaseYangTypes.java @@ -0,0 +1,67 @@ +/* + * 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.controller.sal.binding.yang.types; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +import org.opendaylight.controller.binding.generator.util.Types; +import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public class BaseYangTypes { + + private static Map typeMap = new HashMap(); + + public static final Type BOOLEAN_TYPE = Types.typeForClass(Boolean.class); + public static final Type INT8_TYPE = Types.typeForClass(Byte.class); + public static final Type INT16_TYPE = Types.typeForClass(Short.class); + public static final Type INT32_TYPE = Types.typeForClass(Integer.class); + public static final Type INT64_TYPE = Types.typeForClass(Long.class); + public static final Type STRING_TYPE = Types.typeForClass(String.class); + public static final Type DECIMAL64_TYPE = Types.typeForClass(Double.class); + public static final Type UINT8_TYPE = Types.typeForClass(Short.class); + public static final Type UINT16_TYPE = Types.typeForClass(Integer.class); + public static final Type UINT32_TYPE = Types.typeForClass(Long.class); + public static final Type UINT64_TYPE = Types.typeForClass(BigDecimal.class); + + static { + typeMap.put("boolean", BOOLEAN_TYPE); + typeMap.put("int8", INT8_TYPE); + typeMap.put("int16", INT16_TYPE); + typeMap.put("int32", INT32_TYPE); + typeMap.put("int64", INT64_TYPE); + typeMap.put("string", STRING_TYPE); + typeMap.put("decimal64", DECIMAL64_TYPE); + typeMap.put("uint8", UINT8_TYPE); + typeMap.put("uint16", UINT16_TYPE); + typeMap.put("uint32", UINT32_TYPE); + typeMap.put("uint64", UINT64_TYPE); + + } + + public static final TypeProvider BASE_YANG_TYPES_PROVIDER = new TypeProvider() { + + @Override + public Type javaTypeForYangType(String type) { + return typeMap.get(type); + } + + @Override + public Type javaTypeForSchemaDefinitionType(TypeDefinition type) { + if (type != null) { + return typeMap.get(type.getQName().getLocalName()); + } + + return null; + } + }; + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java new file mode 100644 index 0000000000..2cc774ac83 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java @@ -0,0 +1,45 @@ +/* + * 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.controller.sal.binding.yang.types; + +import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public class TypeProviderImpl implements TypeProvider { + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.type.provider.TypeProvider# + * javaTypeForYangType(java.lang.String) + */ + @Override + public Type javaTypeForYangType(String type) { + Type t = BaseYangTypes.BASE_YANG_TYPES_PROVIDER + .javaTypeForYangType(type); + // TODO: this needs to be implemented in better way + // if(t == null) { + // t = BaseYangTypes.IETF_INET_TYPES_PROVIDER.javaTypeForYangType(type); + // } + return t; + } + + @Override + public Type javaTypeForSchemaDefinitionType(final TypeDefinition type) { + if (type != null) { + Type t = BaseYangTypes.BASE_YANG_TYPES_PROVIDER + .javaTypeForSchemaDefinitionType(type); + + if (t != null) { + return t; + } + } + return null; + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/package-info.java new file mode 100644 index 0000000000..199dfb99ac --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.binding.yang.types; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/BaseTypeProvider.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/BaseTypeProvider.java new file mode 100644 index 0000000000..d771946712 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/BaseTypeProvider.java @@ -0,0 +1,39 @@ +/* + * 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.controller.sal.binding.yang.types.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.opendaylight.controller.binding.generator.util.Types; +import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider; +import org.opendaylight.controller.sal.binding.model.api.ConcreteType; +import org.opendaylight.controller.sal.binding.model.api.ParameterizedType; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.sal.binding.yang.types.BaseYangTypes; + +public class BaseTypeProvider { + + @Test + public void test() { + TypeProvider provider = BaseYangTypes.BASE_YANG_TYPES_PROVIDER; + + Type stringType = provider.javaTypeForYangType("string"); + assertEquals("java.lang", stringType.getPackageName()); + assertEquals("String", stringType.getName()); + assertTrue(stringType instanceof ConcreteType); + ParameterizedType stringBooleanMap = Types.mapTypeFor( + provider.javaTypeForYangType("string"), + provider.javaTypeForYangType("boolean")); + assertTrue(stringBooleanMap instanceof ConcreteType); + assertEquals("java.util", stringBooleanMap.getPackageName()); + assertEquals("Map", stringBooleanMap.getName()); + assertEquals(2, stringBooleanMap.getActualTypeArguments().length); + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/DefinedTypesProviderTest.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/DefinedTypesProviderTest.java new file mode 100644 index 0000000000..3177a5508b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/DefinedTypesProviderTest.java @@ -0,0 +1,12 @@ +/* + * 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.controller.sal.binding.yang.types.test; + +public class DefinedTypesProviderTest { + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/GeneratedTypesTest.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/GeneratedTypesTest.java new file mode 100644 index 0000000000..049f8d98a1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/GeneratedTypesTest.java @@ -0,0 +1,235 @@ +/* + * 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.controller.sal.binding.yang.types.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.junit.Test; +import org.opendaylight.controller.antlrv4.code.gen.YangLexer; +import org.opendaylight.controller.antlrv4.code.gen.YangParser; +import org.opendaylight.controller.model.parser.builder.ModuleBuilder; +import org.opendaylight.controller.model.parser.impl.YangModelParserImpl; +import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator; +import org.opendaylight.controller.sal.binding.generator.impl.BindingGeneratorImpl; +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; +import org.opendaylight.controller.sal.binding.model.api.MethodSignature; +import org.opendaylight.controller.yang.model.api.Module; + +public class GeneratedTypesTest { + + private Module resolveModuleFromFile(final String filePath) { + try { + final InputStream inStream = getClass().getResourceAsStream( + filePath); + if (inStream != null) { + ANTLRInputStream input = new ANTLRInputStream(inStream); + final YangLexer lexer = new YangLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final YangParser parser = new YangParser(tokens); + + final ParseTree tree = parser.yang(); + final ParseTreeWalker walker = new ParseTreeWalker(); + + final YangModelParserImpl modelParser = new YangModelParserImpl(); + walker.walk(modelParser, tree); + + final ModuleBuilder genModule = modelParser.getModuleBuilder(); + final Module module = genModule.build(); + + return module; + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Test + public void testContainerResolving() { + final Module module = resolveModuleFromFile("/simple-container-demo.yang"); + assertTrue(module != null); + + final BindingGenerator bindingGen = new BindingGeneratorImpl(); + final List genTypes = bindingGen.generateTypes(module); + + assertTrue(genTypes != null); + assertEquals(genTypes.size(), 2); + + final GeneratedType simpleContainer = genTypes.get(0); + final GeneratedType nestedContainer = genTypes.get(1); + + assertEquals(simpleContainer.getName(), "SimpleContainer"); + assertEquals(nestedContainer.getName(), "NestedContainer"); + + assertEquals(simpleContainer.getMethodDefinitions().size(), 4); + assertEquals(nestedContainer.getMethodDefinitions().size(), 4); + + int methodsCount = 0; + for (final MethodSignature method : simpleContainer + .getMethodDefinitions()) { + if (method.getName().equals("getFoo")) { + method.getReturnType().getName().equals("Integer"); + methodsCount++; + } + + if (method.getName().equals("setFoo")) { + methodsCount++; + final MethodSignature.Parameter param = method.getParameters() + .get(0); + assertEquals(param.getName(), "foo"); + assertEquals(param.getType().getName(), "Integer"); + } + + if (method.getName().equals("getBar")) { + method.getReturnType().getName().equals("String"); + methodsCount++; + } + + if (method.getName().equals("getNestedContainer")) { + method.getReturnType().getName().equals("NestedContainer"); + methodsCount++; + } + } + assertEquals(methodsCount, 4); + + methodsCount = 0; + for (final MethodSignature method : nestedContainer + .getMethodDefinitions()) { + if (method.getName().equals("getFoo")) { + method.getReturnType().getName().equals("Short"); + methodsCount++; + } + + if (method.getName().equals("setFoo")) { + methodsCount++; + final MethodSignature.Parameter param = method.getParameters() + .get(0); + assertEquals(param.getName(), "foo"); + assertEquals(param.getType().getName(), "Short"); + } + + if (method.getName().equals("getBar")) { + method.getReturnType().getName().equals("String"); + methodsCount++; + } + + if (method.getName().equals("setBar")) { + method.getReturnType().getName().equals("String"); + methodsCount++; + } + } + assertEquals(methodsCount, 4); + } + + @Test + public void testLeafListResolving() { + final Module module = resolveModuleFromFile("/simple-leaf-list-demo.yang"); + assertTrue(module != null); + + final BindingGenerator bindingGen = new BindingGeneratorImpl(); + final List genTypes = bindingGen.generateTypes(module); + + assertTrue(genTypes != null); + assertEquals(genTypes.size(), 2); + + final GeneratedType simpleContainer = genTypes.get(0); + final GeneratedType nestedContainer = genTypes.get(1); + + assertEquals(simpleContainer.getName(), "SimpleContainer"); + assertEquals(nestedContainer.getName(), "NestedContainer"); + + // FIXME: uncomment after fix in DOM tree parser - LeafSchemaNode bad + // isConfig resolving + assertEquals(simpleContainer.getMethodDefinitions().size(), 4); + assertEquals(nestedContainer.getMethodDefinitions().size(), 3); + + int methodsCount = 0; + for (final MethodSignature method : simpleContainer + .getMethodDefinitions()) { + if (method.getName().equals("getFoo")) { + method.getReturnType().getName().equals("List"); + methodsCount++; + } + + if (method.getName().equals("setFoo")) { + methodsCount++; + final MethodSignature.Parameter param = method.getParameters() + .get(0); + assertEquals(param.getName(), "foo"); + assertEquals(param.getType().getName(), "List"); + } + + if (method.getName().equals("getBar")) { + method.getReturnType().getName().equals("String"); + methodsCount++; + } + + if (method.getName().equals("getNestedContainer")) { + method.getReturnType().getName().equals("NestedContainer"); + methodsCount++; + } + } + assertEquals(methodsCount, 4); + + methodsCount = 0; + for (final MethodSignature method : nestedContainer + .getMethodDefinitions()) { + if (method.getName().equals("getFoo")) { + method.getReturnType().getName().equals("Short"); + methodsCount++; + } + + if (method.getName().equals("setFoo")) { + methodsCount++; + final MethodSignature.Parameter param = method.getParameters() + .get(0); + assertEquals(param.getName(), "foo"); + assertEquals(param.getType().getName(), "Short"); + } + + if (method.getName().equals("getBar")) { + method.getReturnType().getName().equals("List"); + methodsCount++; + } + } + assertEquals(methodsCount, 3); + } + + @Test + public void testListResolving() { + final Module module = resolveModuleFromFile("/simple-list-demo.yang"); + assertTrue(module != null); + + final BindingGenerator bindingGen = new BindingGeneratorImpl(); + final List genTypes = bindingGen.generateTypes(module); + + assertTrue(genTypes != null); + assertEquals(genTypes.size(), 3); + } + + @Test + public void testGeneratedTypes() { + final Module module = resolveModuleFromFile("/demo-topology.yang"); + assertTrue(module != null); + + final BindingGenerator bindingGen = new BindingGeneratorImpl(); + final List genTypes = bindingGen.generateTypes(module); + + assertTrue(genTypes != null); + assertEquals(genTypes.size(), 10); + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/package-info.java new file mode 100644 index 0000000000..76e8a9b59e --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.binding.yang.types.test; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/demo-topology.yang b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/demo-topology.yang new file mode 100644 index 0000000000..ba46b6f247 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/demo-topology.yang @@ -0,0 +1,122 @@ +module demo-topology { + yang-version 1; + namespace ""; + prefix "tp"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2013-02-08"{ + reference " WILL BE DEFINED LATER"; + } + + container topology { + description " + This is the model of abstract topology which contains only Network + Nodes and Network Links. Each topology MUST be identified by + unique topology-id for reason that the store could contain many + topologies. + "; + + leaf topology-id { + type string; + description " + It is presumed that datastore will contain many topologies. To + distinguish between topologies it is vital to have UNIQUE + topology identifier. + "; + } + + container network-nodes { + list network-node { + description "The list of network nodes defined for topology."; + + key "node-id"; + + leaf node-id { + type string; + description "The Topology identifier of network-node."; + } + + list network-interface { + key "interface-id"; + + leaf interface-id { + type uint8; + } + + leaf interface-address { + type string; + } + } + + container node-attributes { + description " + Additional attributes that can Network Node contains. + "; + + leaf geo-latitude { + type decimal64 { + fraction-digits 2; + } + config true; + } + + leaf geo-longitude { + type decimal64 { + fraction-digits 2; + } + config true; + } + } + } + } + + container network-links { + list network-link { + description " + The Network Link which is defined by Local (Source) and + Remote (Destination) Network Nodes. Every link MUST be + defined either by identifier and his local and remote + Network Nodes (in real applications it is common that many + links are originated from one node and end up in same + remote node). To ensure that we would always know to + distinguish between links, every link SHOULD have + identifier. + "; + key "link-id"; + + leaf link-id { + type string; + description ""; + } + + container source { + leaf node-id { + type string; + description "Source node identifier."; + } + } + + container destination { + leaf node-id { + type string; + description "Destination node identifier."; + } + } + + container link-attributes { + description "Aditional attributes that can Network Link contains."; + } + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-container-demo.yang b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-container-demo.yang new file mode 100644 index 0000000000..560c3ec861 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-container-demo.yang @@ -0,0 +1,46 @@ +module simple-container-demo { + yang-version 1; + namespace "urn:simple.container.demo"; + prefix "scd"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2012-02-08" { + reference " WILL BE DEFINED LATER"; + } + + revision "2010-02-08" { + reference " WILL BE DEFINED LATER"; + } + + container simple-container { + + leaf foo { + type int32; + } + + leaf bar { + type string; + config true; + } + + container nested-container { + leaf foo { + type uint8; + } + + leaf bar { + type string; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-leaf-list-demo.yang b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-leaf-list-demo.yang new file mode 100644 index 0000000000..78017bb3d7 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-leaf-list-demo.yang @@ -0,0 +1,47 @@ +module simple-leaf-list-demo { + yang-version 1; + namespace "urn:simple.leaf-list.demo"; + prefix "scd"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2012-02-08" { + reference " WILL BE DEFINED LATER"; + } + + revision "2010-02-08" { + reference " WILL BE DEFINED LATER"; + } + + container simple-container { + + leaf-list foo { + type int32; + } + + leaf bar { + type string; + config true; + } + + container nested-container { + leaf foo { + type uint8; + } + + leaf-list bar { + type string; + config true; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-list-demo.yang b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-list-demo.yang new file mode 100644 index 0000000000..059bc080ad --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/simple-list-demo.yang @@ -0,0 +1,50 @@ +module simple-list-demo { + yang-version 1; + namespace "urn:simple.container.demo"; + prefix "scd"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2013-02-27" { + reference " WILL BE DEFINED LATER"; + } + + container list-parent-container { + + list simple-list { + key "list-key"; + + leaf list-key { + type int8; + } + + container list-child-container { + leaf foo { + type uint8; + } + } + + leaf foo { + type int32; + } + + leaf-list simple-leaf-list { + type int32; + } + + leaf bar { + type string; + config true; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/pom.xml b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/pom.xml new file mode 100644 index 0000000000..97e5780a4d --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + org.opendaylight.controller + binding-generator + 1.0 + + binding-generator-spi + + + org.opendaylight.controller + binding-model-api + 1.0 + + + org.opendaylight.controller + yang-model-api + 1.0 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/BindingGeneratorServiceProvider.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/BindingGeneratorServiceProvider.java new file mode 100644 index 0000000000..2677221f05 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/BindingGeneratorServiceProvider.java @@ -0,0 +1,13 @@ +/* + * 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.controller.sal.binding.generator.spi; + +public interface BindingGeneratorServiceProvider { + + public void registerTypeProvider(final TypeProvider provider); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/TypeProvider.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/TypeProvider.java new file mode 100644 index 0000000000..3c00dee98e --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/TypeProvider.java @@ -0,0 +1,19 @@ +/* + * 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.controller.sal.binding.generator.spi; + +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface TypeProvider { + + @Deprecated + Type javaTypeForYangType(String type); + + Type javaTypeForSchemaDefinitionType(final TypeDefinition type); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/TypeProviderFactory.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/TypeProviderFactory.java new file mode 100644 index 0000000000..1b9156d4c7 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/TypeProviderFactory.java @@ -0,0 +1,13 @@ +/* + * 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.controller.sal.binding.generator.spi; + +public interface TypeProviderFactory { + + TypeProvider providerFor(YANGModuleIdentifier module); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/YANGModuleIdentifier.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/YANGModuleIdentifier.java new file mode 100644 index 0000000000..8c547f412f --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/YANGModuleIdentifier.java @@ -0,0 +1,17 @@ +/* + * 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.controller.sal.binding.generator.spi; + +import java.net.URI; +import java.util.Date; + +public class YANGModuleIdentifier { + String name; + URI namespace; + Date revision; +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/package-info.java new file mode 100644 index 0000000000..bf15d8636d --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-spi/src/main/java/org/opendaylight/controller/sal/binding/generator/spi/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.binding.generator.spi; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/pom.xml b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/pom.xml new file mode 100644 index 0000000000..8022cf4745 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/pom.xml @@ -0,0 +1,16 @@ + + 4.0.0 + + org.opendaylight.controller + binding-generator + 1.0 + + binding-generator-util + + + org.opendaylight.controller + binding-model-api + 1.0 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/AbstractBaseType.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/AbstractBaseType.java new file mode 100644 index 0000000000..5496cf96ac --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/AbstractBaseType.java @@ -0,0 +1,71 @@ +/* + * 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.controller.binding.generator.util; + +import org.opendaylight.controller.sal.binding.model.api.Type; + +public class AbstractBaseType implements Type { + + private final String packageName; + private final String name; + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public String getName() { + + return name; + } + + protected AbstractBaseType(String pkName, String name) { + this.packageName = pkName; + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((packageName == null) ? 0 : packageName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Type other = (Type) obj; + if (name == null) { + if (other.getName() != null) + return false; + } else if (!name.equals(other.getPackageName())) + return false; + if (packageName == null) { + if (other.getPackageName() != null) + return false; + } else if (!packageName.equals(other.getPackageName())) + return false; + return true; + } + + @Override + public String toString() { + + return "Type (" + packageName + "." + name + ")"; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/CodeGeneratorHelper.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/CodeGeneratorHelper.java new file mode 100644 index 0000000000..552be98295 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/CodeGeneratorHelper.java @@ -0,0 +1,67 @@ +/* + * 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.controller.binding.generator.util; + +public class CodeGeneratorHelper { + + public static String parseToClassName(String token) { + String correctStr = parseToCamelCase(token); + + // make first char upper-case + char first = Character.toUpperCase(correctStr.charAt(0)); + correctStr = first + correctStr.substring(1); + return correctStr; + } + + public static String parseToParamName(String token) { + String correctStr = parseToCamelCase(token); + + // make first char lower-case + char first = Character.toLowerCase(correctStr.charAt(0)); + correctStr = first + correctStr.substring(1); + return correctStr; + } + + private static String parseToCamelCase(String token) { + if (token == null) { + throw new NullPointerException("Name can not be null"); + } + + String correctStr = token.trim(); + if (correctStr.length() == 0) { + throw new IllegalArgumentException("Name can not be emty"); + } + + correctStr = replaceWithCamelCase(correctStr, ' '); + correctStr = replaceWithCamelCase(correctStr, '-'); + correctStr = replaceWithCamelCase(correctStr, '_'); + return correctStr; + } + + private static String replaceWithCamelCase(String text, char removalChar) { + StringBuilder sb = new StringBuilder(text); + String toBeRemoved = String.valueOf(removalChar); + + int toBeRemovedPos = sb.indexOf(toBeRemoved); + while (toBeRemovedPos != -1) { + sb.replace(toBeRemovedPos, toBeRemovedPos + 1, ""); + // check if 'toBeRemoved' character is not the only character in + // 'text' + if (sb.length() == 0) { + throw new IllegalArgumentException("Name can not be '" + + toBeRemoved + "'"); + } + String replacement = String.valueOf(sb.charAt(toBeRemovedPos)) + .toUpperCase(); + sb.setCharAt(toBeRemovedPos, replacement.charAt(0)); + toBeRemovedPos = sb.indexOf(toBeRemoved); + } + return sb.toString(); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/Types.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/Types.java new file mode 100644 index 0000000000..8c65b4a26c --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/Types.java @@ -0,0 +1,122 @@ +/* + * 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.controller.binding.generator.util; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.sal.binding.model.api.ConcreteType; +import org.opendaylight.controller.sal.binding.model.api.ParameterizedType; +import org.opendaylight.controller.sal.binding.model.api.Type; + +public class Types { + private static final Type SET_TYPE = typeForClass(Set.class); + private static final Type LIST_TYPE = typeForClass(List.class); + private static final Type MAP_TYPE = typeForClass(Map.class); + + private Types() { + } + + public static ConcreteType voidType() { + return new ConcreteTypeImpl(Void.class.getPackage().getName(), + Void.class.getSimpleName()); + } + + /** + * Returns an instance of {@link ConcreteType} describing the class + * + * @param cls + * Class to describe + * @return Description of class + */ + public static ConcreteType typeForClass(Class cls) { + return new ConcreteTypeImpl(cls.getPackage().getName(), + cls.getSimpleName()); + } + + /** + * Returns an instance of {@link ParameterizedType} describing the typed + * {@link Map} + * + * @param keyType + * Key Type + * @param valueType + * Value Type + * @return Description of generic type instance + */ + public static ParameterizedType mapTypeFor(Type keyType, Type valueType) { + return parameterizedTypeFor(MAP_TYPE, keyType, valueType); + } + + /** + * Returns an instance of {@link ParameterizedType} describing the typed + * {@link Set} with concrete type of value. + * + * @param valueType + * Value Type + * @return Description of generic type instance of Set + */ + public static ParameterizedType setTypeFor(Type valueType) { + return parameterizedTypeFor(SET_TYPE, valueType); + } + + /** + * Returns an instance of {@link ParameterizedType} describing the typed + * {@link List} with concrete type of value. + * + * @param valueType + * Value Type + * @return Description of type instance of List + */ + public static ParameterizedType listTypeFor(Type valueType) { + return parameterizedTypeFor(LIST_TYPE, valueType); + } + + /** + * + * @param type + * @param parameters + * @return + */ + public static ParameterizedType parameterizedTypeFor(Type type, + Type... parameters) { + return new ParametrizedTypeImpl(type, parameters); + } + + private static class ConcreteTypeImpl extends AbstractBaseType implements + ConcreteType { + private ConcreteTypeImpl(String pkName, String name) { + super(pkName, name); + } + } + + private static class ParametrizedTypeImpl extends AbstractBaseType + implements ParameterizedType { + private Type[] actualTypes; + private Type rawType; + + @Override + public Type[] getActualTypeArguments() { + + return actualTypes; + } + + @Override + public Type getRawType() { + return rawType; + } + + public ParametrizedTypeImpl(Type rawType, Type[] actTypes) { + super(rawType.getPackageName(), rawType.getName()); + this.rawType = rawType; + this.actualTypes = actTypes; + } + + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/package-info.java new file mode 100644 index 0000000000..a5aa2a049e --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.binding.generator.util; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/pom.xml b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/pom.xml new file mode 100644 index 0000000000..661dcaa737 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/pom.xml @@ -0,0 +1,22 @@ + + 4.0.0 + + org.opendaylight.controller + binding-generator + 1.0 + + binding-java-api-generator + + + org.opendaylight.controller + binding-model-api + 1.0 + + + org.opendaylight.controller + binding-generator-impl + 1.0 + test + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/CompositeKeyGenerator.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/CompositeKeyGenerator.java new file mode 100644 index 0000000000..4e50f6028c --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/CompositeKeyGenerator.java @@ -0,0 +1,54 @@ +/* + * 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.controller.sal.java.api.generator; + +import static org.opendaylight.controller.sal.java.api.generator.Constants.*; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.List; + +import org.opendaylight.controller.sal.binding.model.api.CodeGenerator; +import org.opendaylight.controller.sal.binding.model.api.Constant; +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; + +public class CompositeKeyGenerator implements CodeGenerator { + + @Override + public Writer generate(GeneratedType type) throws IOException { + final Writer writer = new StringWriter(); + final List fields = type.getConstantDefinitions(); + + writer.write(GeneratorUtil.createClassDeclarationWithPkgName( + type.getPackageName(), type.getName(), "")); + writer.write(NL); + writer.write(NL); + + if (fields != null) { + for (Constant field : fields) { + writer.write(GeneratorUtil.createField(field, TAB) + NL); + } + writer.write(NL); + + for (Constant field : fields) { + writer.write(GeneratorUtil.createGetter(field, TAB) + NL); + } + writer.write(NL); + + writer.write(GeneratorUtil.createHashCode(fields, TAB) + NL); + writer.write(GeneratorUtil.createEquals(type, fields, TAB) + NL); + writer.write(GeneratorUtil.createToString(type, fields, TAB) + NL); + + writer.write(RCB); + } + + return writer; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/Constants.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/Constants.java new file mode 100644 index 0000000000..37408bc071 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/Constants.java @@ -0,0 +1,34 @@ +/* + * 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.controller.sal.java.api.generator; + +public class Constants { + + public static final String IFC = "interface"; + public static final String CLASS = "class"; + public static final String PKG = "package"; + public static final String ENUM = "enum"; + + public static final String LCB = "{"; + public static final String RCB = "}"; + + public static final String LB = "("; + public static final String RB = ")"; + + public static final String GAP = " "; + public static final String COMMA = ","; + public static final String NL = "\n"; + public static final String SC = ";"; + public static final String TAB = "\t"; + + public static final String PUBLIC = "public"; + public static final String PRIVATE = "private"; + public static final String STATIC = "static"; + public static final String FINAL = "final"; + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/GeneratorJavaFile.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/GeneratorJavaFile.java new file mode 100644 index 0000000000..794487594e --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/GeneratorJavaFile.java @@ -0,0 +1,110 @@ +/* + * 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.controller.sal.java.api.generator; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.opendaylight.controller.sal.binding.model.api.CodeGenerator; +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; + +public class GeneratorJavaFile { + + private final CodeGenerator codeGenerator; + private final Set types; + + public GeneratorJavaFile(CodeGenerator codeGenerator, + Set types) { + this.codeGenerator = codeGenerator; + this.types = types; + } + + public boolean generateToFile() { + return generateToFile(null); + } + + public boolean generateToFile(String path) { + try { + for (GeneratedType type : types) { + String parentPath = generateParentPath(path, + type.getPackageName()); + + File file = new File(parentPath, type.getName() + ".java"); + File parent = file.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + + if (!file.exists()) { + FileWriter fw = null; + BufferedWriter bw = null; + + file.createNewFile(); + fw = new FileWriter(file); + bw = new BufferedWriter(fw); + Writer writer = codeGenerator.generate(type); + bw.write(writer.toString()); + + if (bw != null) { + try { + bw.close(); + } catch (IOException e) { + // TODO: log? + } + } + } + } + return true; + } catch (IOException e) { + // TODO: log? + return false; + } + } + + private String generateParentPath(String path, String pkg) { + List dirs = new ArrayList(); + String pkgPath = ""; + if (pkg != null) { + if (pkg.length() > 0) { + if (pkg.contains(".")) { + String[] split = pkg.split("\\."); + for (String dir : split) { + dirs.add(dir); + } + } else { + dirs.add(pkg); + } + for (int i = 0; i < dirs.size(); i++) { + if (i == 0) { + pkgPath += dirs.get(i); + } else { + pkgPath += File.separator + dirs.get(i); + } + } + } + } + String fullPath = ""; + if (path != null) { + if (path.endsWith(File.separator)) { + fullPath = path + pkgPath; + } else { + fullPath = path + File.separator + pkgPath; + } + } else { + fullPath = pkgPath; + } + return fullPath; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/GeneratorUtil.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/GeneratorUtil.java new file mode 100644 index 0000000000..673d37e86b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/GeneratorUtil.java @@ -0,0 +1,286 @@ +/* + * 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.controller.sal.java.api.generator; + +import static org.opendaylight.controller.sal.java.api.generator.Constants.*; + +import java.util.List; + +import org.opendaylight.controller.sal.binding.model.api.Constant; +import org.opendaylight.controller.sal.binding.model.api.Enumeration; +import org.opendaylight.controller.sal.binding.model.api.MethodSignature; +import org.opendaylight.controller.sal.binding.model.api.ParameterizedType; +import org.opendaylight.controller.sal.binding.model.api.Type; +import org.opendaylight.controller.sal.binding.model.api.Enumeration.Pair; +import org.opendaylight.controller.sal.binding.model.api.MethodSignature.Parameter; + +public class GeneratorUtil { + + private GeneratorUtil() { + } + + public static String createIfcDeclarationWithPkgName(String packageName, + String name, String indent) { + return createFileDeclarationWithPkgName(IFC, packageName, name, indent); + } + + public static String createClassDeclarationWithPkgName(String packageName, + String name, String indent) { + return createFileDeclarationWithPkgName(CLASS, packageName, name, + indent); + } + + private static String createFileDeclarationWithPkgName(String type, + String packageName, String name, String indent) { + StringBuilder sb = new StringBuilder(); + sb.append(PKG + GAP + packageName + SC); + sb.append(NL); + sb.append(NL); + sb.append(PUBLIC + GAP + type + GAP + name + GAP + LCB); + return sb.toString(); + } + + public static String createConstant(Constant constant, String indent) { + StringBuilder sb = new StringBuilder(); + sb.append(indent + PUBLIC + GAP + STATIC + GAP + FINAL + GAP); + sb.append(getExplicitType(constant.getType()) + GAP + + constant.getName()); + sb.append(GAP + "=" + GAP); + sb.append(constant.getValue() + SC); + return sb.toString(); + } + + public static String createField(Constant field, String indent) { + StringBuilder sb = new StringBuilder(); + sb.append(indent + PRIVATE + GAP); + sb.append(getExplicitType(field.getType()) + GAP + field.getName()); + sb.append(GAP + "=" + GAP); + sb.append(field.getValue() + SC); + return sb.toString(); + } + + /** + * Create method declaration in interface. + * + * @param method + * @param indent + * @return + */ + public static String createMethodDeclaration(MethodSignature method, + String indent) { + String comment = method.getComment(); + Type type = method.getReturnType(); + String name = method.getName(); + List parameters = method.getParameters(); + + StringBuilder sb = new StringBuilder(); + createComment(sb, comment, indent); + + sb.append(indent + getExplicitType(type) + GAP + name); + sb.append(LB); + for (int i = 0; i < parameters.size(); i++) { + Parameter p = parameters.get(i); + String separator = COMMA; + if (i + 1 == parameters.size()) { + separator = ""; + } + sb.append(getExplicitType(p.getType()) + GAP + p.getName() + + separator); + } + sb.append(RB); + sb.append(SC); + + return sb.toString(); + } + + public static String createGetter(Constant field, String indent) { + StringBuilder sb = new StringBuilder(); + + Type type = field.getType(); + String varName = field.getName(); + char first = Character.toUpperCase(varName.charAt(0)); + String methodName = "get" + first + varName.substring(1); + + sb.append(indent + PUBLIC + GAP + getExplicitType(type) + GAP + + methodName); + sb.append(LB + RB + LCB + NL); + + String currentIndent = indent + TAB; + + sb.append(currentIndent + "return " + varName + SC + NL); + + sb.append(indent + RCB); + return sb.toString(); + } + + public static String createHashCode(List fields, String indent) { + StringBuilder sb = new StringBuilder(); + sb.append(indent + "public int hashCode() {" + NL); + sb.append(indent + TAB + "final int prime = 31;" + NL); + sb.append(indent + TAB + "int result = 1;" + NL); + + for (Constant field : fields) { + String fieldName = field.getName(); + sb.append(indent + TAB + "result = prime * result + ((" + fieldName + + " == null) ? 0 : " + fieldName + ".hashCode());" + NL); + } + + sb.append(indent + TAB + "return result;" + NL); + sb.append(indent + RCB + NL); + return sb.toString(); + } + + public static String createEquals(Type type, List fields, + String indent) { + StringBuilder sb = new StringBuilder(); + final String indent1 = indent + TAB; + final String indent2 = indent + TAB + TAB; + final String indent3 = indent + TAB + TAB + TAB; + + sb.append(indent + "public boolean equals(Object obj) {" + NL); + sb.append(indent1 + "if (this == obj) {" + NL); + sb.append(indent2 + "return true;" + NL); + sb.append(indent1 + "}" + NL); + sb.append(indent1 + "if (obj == null) {" + NL); + sb.append(indent2 + "return false;" + NL); + sb.append(indent1 + "}" + NL); + sb.append(indent1 + "if (getClass() != obj.getClass()) {" + NL); + sb.append(indent2 + "return false;" + NL); + sb.append(indent1 + "}" + NL); + + String typeStr = type.getPackageName() + "." + type.getName(); + sb.append(indent1 + typeStr + " other = (" + typeStr + ") obj;" + NL); + + for (Constant field : fields) { + String fieldName = field.getName(); + sb.append(indent1 + "if (" + fieldName + " == null) {" + NL); + sb.append(indent2 + "if (other." + fieldName + " != null) {" + NL); + sb.append(indent3 + "return false;" + NL); + sb.append(indent2 + "}" + NL); + sb.append(indent1 + "} else if (!" + fieldName + ".equals(other." + + fieldName + ")) {" + NL); + sb.append(indent2 + "return false;" + NL); + sb.append(indent1 + "}" + NL); + } + + sb.append(indent1 + "return true;" + NL); + + sb.append(indent + RCB + NL); + return sb.toString(); + } + + public static String createToString(Type type, List fields, + String indent) { + StringBuilder sb = new StringBuilder(); + String typeStr = type.getPackageName() + "." + type.getName(); + + sb.append(indent + "public String toString() {" + NL); + sb.append(indent + TAB + "return \"" + typeStr + "["); + + boolean first = true; + for (Constant field : fields) { + String fieldName = field.getName(); + String fieldType = field.getType().getPackageName() + "." + + field.getType().getName(); + if (first) { + if (fieldType.equals("java.lang.String")) { + sb.append(fieldName + "=\\\"" + + parseStringValue((String) field.getValue()) + + "\\\""); + } else { + sb.append(fieldName + "=" + field.getValue() + ""); + } + } else { + if (fieldType.equals("java.lang.String")) { + sb.append(", " + fieldName + "=\\\"" + + parseStringValue((String) field.getValue()) + + "\\\""); + } else { + sb.append(", " + fieldName + "=" + field.getValue() + ""); + } + + } + first = false; + } + sb.append("]\"" + SC + NL); + + sb.append(indent + RCB + NL); + return sb.toString(); + } + + /** + * Remove starting and ending quote sign + * + * @param o + * @return + */ + private static String parseStringValue(String str) { + return str.substring(1, str.length() - 1); + } + + public static String createEnum(Enumeration e, String indent) { + StringBuilder sb = new StringBuilder(indent + ENUM + GAP + e.getName() + + GAP + LCB + NL); + + String separator = COMMA; + List values = e.getValues(); + sb.append(indent + TAB); + for (int i = 0; i < values.size(); i++) { + if (i + 1 == values.size()) { + separator = SC; + } + sb.append(values.get(i).getName() + separator); + } + sb.append(NL); + sb.append(indent + RCB); + return sb.toString(); + } + + private static String getExplicitType(Type type) { + String packageName = type.getPackageName(); + if (packageName.endsWith(".")) { + packageName = packageName.substring(0, packageName.length() - 1); + } + StringBuilder sb = new StringBuilder(packageName + "." + type.getName()); + if (type instanceof ParameterizedType) { + ParameterizedType pType = (ParameterizedType) type; + Type[] pTypes = pType.getActualTypeArguments(); + sb.append("<"); + sb.append(getParameters(pTypes)); + sb.append(">"); + } + if (sb.toString().equals("java.lang.Void")) { + return "void"; + } + return sb.toString(); + } + + private static String getParameters(Type[] pTypes) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < pTypes.length; i++) { + Type t = pTypes[i]; + + String separator = COMMA; + if (i + 1 == pTypes.length) { + separator = ""; + } + sb.append(getExplicitType(t) + separator); + } + return sb.toString(); + } + + private static void createComment(StringBuilder sb, String comment, + String indent) { + if (comment != null && comment.length() > 0) { + sb.append(indent + "/*" + NL); + sb.append(indent + comment + NL); + sb.append(indent + "*/" + NL); + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/InterfaceGenerator.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/InterfaceGenerator.java new file mode 100644 index 0000000000..8a0054bd8a --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/InterfaceGenerator.java @@ -0,0 +1,61 @@ +/* + * 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.controller.sal.java.api.generator; + +import static org.opendaylight.controller.sal.java.api.generator.Constants.*; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.List; + +import org.opendaylight.controller.sal.binding.model.api.CodeGenerator; +import org.opendaylight.controller.sal.binding.model.api.Constant; +import org.opendaylight.controller.sal.binding.model.api.Enumeration; +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; +import org.opendaylight.controller.sal.binding.model.api.MethodSignature; + +public class InterfaceGenerator implements CodeGenerator { + + public Writer generate(GeneratedType type) throws IOException { + Writer writer = new StringWriter(); + final List constants = type.getConstantDefinitions(); + final List methods = type.getMethodDefinitions(); + final List enums = type.getEnumDefintions(); + + writer.write(GeneratorUtil.createIfcDeclarationWithPkgName( + type.getPackageName(), type.getName(), "")); + writer.write(NL); + + if (constants != null) { + for (Constant c : constants) { + writer.write(GeneratorUtil.createConstant(c, TAB) + NL); + } + writer.write(NL); + } + + if (methods != null) { + for (MethodSignature m : methods) { + writer.write(GeneratorUtil.createMethodDeclaration(m, TAB) + NL); + } + writer.write(NL); + } + + if (enums != null) { + for (Enumeration e : enums) { + writer.write(GeneratorUtil.createEnum(e, TAB) + NL); + } + writer.write(NL); + } + + writer.write(RCB); + + return writer; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/package-info.java new file mode 100644 index 0000000000..c202f76498 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.java.api.generator; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/controller/sal/java/api/generator/test/GeneratorJavaFileTest.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/controller/sal/java/api/generator/test/GeneratorJavaFileTest.java new file mode 100644 index 0000000000..36d0fbc28c --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/controller/sal/java/api/generator/test/GeneratorJavaFileTest.java @@ -0,0 +1,87 @@ +/* + * 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.controller.sal.java.api.generator.test; + +import static org.junit.Assert.*; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.sal.binding.generator.impl.GeneratedTypeBuilderImpl; +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; +import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder; +import org.opendaylight.controller.sal.java.api.generator.GeneratorJavaFile; +import org.opendaylight.controller.sal.java.api.generator.InterfaceGenerator; + +public class GeneratorJavaFileTest { + + private static final String FS = File.separator; + private static final String PATH = "test-dir"; + private final File testDir = new File(PATH); + + @Before + public void init() { + assertTrue(testDir.mkdir()); + } + + @After + public void cleanUp() { + deleteTestDir(testDir); + } + + @Test + public void test() { + final Set types = new HashSet(); + GeneratedType t1 = createGeneratedType( + "org.opendaylight.controller.gen", "Type1"); + GeneratedType t2 = createGeneratedType( + "org.opendaylight.controller.gen", "Type2"); + GeneratedType t3 = createGeneratedType( + "org.opendaylight.controller.gen", "Type3"); + types.add(t1); + types.add(t2); + types.add(t3); + GeneratorJavaFile generator = new GeneratorJavaFile( + new InterfaceGenerator(), types); + generator.generateToFile(PATH); + + // path: test-dir/com/cisco/yang + String[] files = new File(PATH + FS + "com" + FS + "cisco" + FS + + "yang").list(); + List filesList = Arrays.asList(files); + + assertEquals(3, files.length); + assertTrue(filesList.contains("Type1.java")); + assertTrue(filesList.contains("Type2.java")); + assertTrue(filesList.contains("Type3.java")); + } + + private GeneratedType createGeneratedType(String pkgName, String name) { + GeneratedTypeBuilder builder = new GeneratedTypeBuilderImpl(pkgName, + name); + return builder.toInstance(); + } + + private void deleteTestDir(File file) { + if (file.isDirectory()) { + for (File f : file.listFiles()) { + deleteTestDir(f); + } + } + if (!file.delete()) { + throw new RuntimeException("Failed to clean up after test"); + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/controller/sal/java/api/generator/test/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/controller/sal/java/api/generator/test/package-info.java new file mode 100644 index 0000000000..82d666839e --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/controller/sal/java/api/generator/test/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.java.api.generator.test; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/abstract-topology.yang b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/abstract-topology.yang new file mode 100644 index 0000000000..b0dff3c505 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/abstract-topology.yang @@ -0,0 +1,131 @@ +// vi: set smarttab sw=4 tabstop=4: +module abstract-topology { + yang-version 1; + namespace ""; + prefix "tp"; + + import ietf-inet-types { prefix "inet"; } + import abstract-prefixes { prefix "abs-pref"; } + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2013-02-08" { + reference " WILL BE DEFINED LATER"; + } + + revision "2013-03-08" { + reference " WILL BE DEFINED LATER"; + } + + revision "2012-02-08" { + reference " WILL BE DEFINED LATER"; + } + + typedef topology-id-ref { + type leafref { + path "/tp:topology/tp:topology-id"; + } + description "This type is used for leafs that reference topology identifier instance."; + } + + typedef network-node-id-ref { + type leafref { + path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id"; + } + description "This type is used for leafs that reference network node instance."; + } + + typedef link-id-ref { + type leafref { + path "/tp:topology/tp:network-links/tp:network-link/tp:link-id"; + } + description "This type is used for leafs that reference network link instance."; + } + + container topology { + description " + This is the model of abstract topology which contains only Network + Nodes and Network Links. Each topology MUST be identified by + unique topology-id for reason that the store could contain many + topologies. + "; + + leaf topology-id { + type inet:uri; + description " + It is presumed that datastore will contain many topologies. To + distinguish between topologies it is vital to have UNIQUE + topology identifier. + "; + } + + container network-nodes { + list network-node { + description "The list of network nodes defined for topology."; + + key "node-id"; + + leaf node-id { + type inet:uri; + description "The Topology identifier of network-node."; + } + + container attributes { + description " + Additional attributes that can Network Node contains. + "; + } + } + } + + container network-links { + list network-link { + description " + The Network Link which is defined by Local (Source) and + Remote (Destination) Network Nodes. Every link MUST be + defined either by identifier and his local and remote + Network Nodes (in real applications it is common that many + links are originated from one node and end up in same + remote node). To ensure that we would always know to + distinguish between links, every link SHOULD have + identifier. + "; + key "link-id"; + + leaf link-id { + type inet:uri; + description ""; + } + + container source { + leaf node-id { + type node-id-ref; + description "Source node identifier."; + } + } + + container destination { + leaf node-id { + type node-id-ref; + description "Destination node identifier."; + } + } + + container attributes { + description "Aditional attributes that can Network Link contains."; + } + } + } + } + + //TODO: add base operations +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/demo-topology.yang b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/demo-topology.yang new file mode 100644 index 0000000000..ba46b6f247 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/demo-topology.yang @@ -0,0 +1,122 @@ +module demo-topology { + yang-version 1; + namespace ""; + prefix "tp"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2013-02-08"{ + reference " WILL BE DEFINED LATER"; + } + + container topology { + description " + This is the model of abstract topology which contains only Network + Nodes and Network Links. Each topology MUST be identified by + unique topology-id for reason that the store could contain many + topologies. + "; + + leaf topology-id { + type string; + description " + It is presumed that datastore will contain many topologies. To + distinguish between topologies it is vital to have UNIQUE + topology identifier. + "; + } + + container network-nodes { + list network-node { + description "The list of network nodes defined for topology."; + + key "node-id"; + + leaf node-id { + type string; + description "The Topology identifier of network-node."; + } + + list network-interface { + key "interface-id"; + + leaf interface-id { + type uint8; + } + + leaf interface-address { + type string; + } + } + + container node-attributes { + description " + Additional attributes that can Network Node contains. + "; + + leaf geo-latitude { + type decimal64 { + fraction-digits 2; + } + config true; + } + + leaf geo-longitude { + type decimal64 { + fraction-digits 2; + } + config true; + } + } + } + } + + container network-links { + list network-link { + description " + The Network Link which is defined by Local (Source) and + Remote (Destination) Network Nodes. Every link MUST be + defined either by identifier and his local and remote + Network Nodes (in real applications it is common that many + links are originated from one node and end up in same + remote node). To ensure that we would always know to + distinguish between links, every link SHOULD have + identifier. + "; + key "link-id"; + + leaf link-id { + type string; + description ""; + } + + container source { + leaf node-id { + type string; + description "Source node identifier."; + } + } + + container destination { + leaf node-id { + type string; + description "Destination node identifier."; + } + } + + container link-attributes { + description "Aditional attributes that can Network Link contains."; + } + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-container-demo.yang b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-container-demo.yang new file mode 100644 index 0000000000..560c3ec861 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-container-demo.yang @@ -0,0 +1,46 @@ +module simple-container-demo { + yang-version 1; + namespace "urn:simple.container.demo"; + prefix "scd"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2012-02-08" { + reference " WILL BE DEFINED LATER"; + } + + revision "2010-02-08" { + reference " WILL BE DEFINED LATER"; + } + + container simple-container { + + leaf foo { + type int32; + } + + leaf bar { + type string; + config true; + } + + container nested-container { + leaf foo { + type uint8; + } + + leaf bar { + type string; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-leaf-list-demo.yang b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-leaf-list-demo.yang new file mode 100644 index 0000000000..78017bb3d7 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-leaf-list-demo.yang @@ -0,0 +1,47 @@ +module simple-leaf-list-demo { + yang-version 1; + namespace "urn:simple.leaf-list.demo"; + prefix "scd"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2012-02-08" { + reference " WILL BE DEFINED LATER"; + } + + revision "2010-02-08" { + reference " WILL BE DEFINED LATER"; + } + + container simple-container { + + leaf-list foo { + type int32; + } + + leaf bar { + type string; + config true; + } + + container nested-container { + leaf foo { + type uint8; + } + + leaf-list bar { + type string; + config true; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-list-demo.yang b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-list-demo.yang new file mode 100644 index 0000000000..059bc080ad --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/resources/simple-list-demo.yang @@ -0,0 +1,50 @@ +module simple-list-demo { + yang-version 1; + namespace "urn:simple.container.demo"; + prefix "scd"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2013-02-27" { + reference " WILL BE DEFINED LATER"; + } + + container list-parent-container { + + list simple-list { + key "list-key"; + + leaf list-key { + type int8; + } + + container list-child-container { + leaf foo { + type uint8; + } + } + + leaf foo { + type int32; + } + + leaf-list simple-leaf-list { + type int32; + } + + leaf bar { + type string; + config true; + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/pom.xml b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/pom.xml new file mode 100644 index 0000000000..c9e60b6a14 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + + org.opendaylight.controller + binding-generator + 1.0 + + binding-model-api + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/AccessModifier.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/AccessModifier.java new file mode 100644 index 0000000000..5096dd88f8 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/AccessModifier.java @@ -0,0 +1,12 @@ +/* + * 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.controller.sal.binding.model.api; + +public enum AccessModifier { + PRIVATE, PUBLIC, PROTECTED +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/CodeGenerator.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/CodeGenerator.java new file mode 100644 index 0000000000..6e8d317d4c --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/CodeGenerator.java @@ -0,0 +1,17 @@ +/* + * 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.controller.sal.binding.model.api; + +import java.io.IOException; +import java.io.Writer; + +public interface CodeGenerator { + + Writer generate(GeneratedType type) throws IOException; + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/ConcreteType.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/ConcreteType.java new file mode 100644 index 0000000000..ea11abacdb --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/ConcreteType.java @@ -0,0 +1,12 @@ +/* + * 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.controller.sal.binding.model.api; + +public interface ConcreteType extends Type { + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Constant.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Constant.java new file mode 100644 index 0000000000..cad3460913 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Constant.java @@ -0,0 +1,21 @@ +/* + * 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.controller.sal.binding.model.api; + +public interface Constant { + + public Type getDefiningType(); + + public Type getType(); + + public String getName(); + + public Object getValue(); + + public String toFormattedString(); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Enumeration.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Enumeration.java new file mode 100644 index 0000000000..bfce017cd5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Enumeration.java @@ -0,0 +1,26 @@ +/* + * 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.controller.sal.binding.model.api; + +import java.util.List; + +public interface Enumeration extends Type { + + public Type getDefiningType(); + + public List getValues(); + + public String toFormattedString(); + + interface Pair { + + public String getName(); + + public Integer getValue(); + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedProperty.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedProperty.java new file mode 100644 index 0000000000..462e1e1f63 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedProperty.java @@ -0,0 +1,15 @@ +/* + * 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.controller.sal.binding.model.api; + +public interface GeneratedProperty extends MethodSignature { + + public boolean isReadOnly(); + + public boolean isFinal(); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedTransferObject.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedTransferObject.java new file mode 100644 index 0000000000..4bed98a26b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedTransferObject.java @@ -0,0 +1,29 @@ +/* + * 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.controller.sal.binding.model.api; + +import java.util.List; +import java.util.Set; + +public interface GeneratedTransferObject extends Type { + + /** + * Returns Set of all Enumerator definitions associated with interface. + * + * @return Set of all Enumerator definitions associated with interface. + */ + public List getEnumDefintions(); + + public List getProperties(); + + public List getEqualsIdentifiers(); + + public List getHashCodeIdentifiers(); + + public List getToStringIdentifiers(); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedType.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedType.java new file mode 100644 index 0000000000..538231147a --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/GeneratedType.java @@ -0,0 +1,56 @@ +/* + * 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.controller.sal.binding.model.api; + +import java.util.List; + +/** + * Every Java interface has to be specified with: + *
    + *
  • package that belongs into
  • + *
  • interface name (with commentary that SHOULD be + * present to proper define interface and base contracts specified for + * interface)
  • + *
  • enum and constant definitions (i.e. each + * constant definition is by default defined as public static final + * + type (either primitive or object) and constant name
  • + *
  • method definitions with specified input parameters (with + * types) and return values
  • + *
+ * + * By the definition of the interface constant, enum and method definitions MUST + * be public, so there is no need to specify the scope of visibility. + * + * + */ +public interface GeneratedType extends Type { + + public Type getParentType(); + + /** + * Returns Set of all Enumerator definitions associated with interface. + * + * @return Set of all Enumerator definitions associated with interface. + */ + public List getEnumDefintions(); + + /** + * + * + * @return + */ + public List getConstantDefinitions(); + + /** + * + * + * @return + */ + public List getMethodDefinitions(); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/MethodSignature.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/MethodSignature.java new file mode 100644 index 0000000000..603ffdb652 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/MethodSignature.java @@ -0,0 +1,31 @@ +/* + * 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.controller.sal.binding.model.api; + +import java.util.List; + +public interface MethodSignature { + + public String getName(); + + public String getComment(); + + public Type getDefiningType(); + + public Type getReturnType(); + + public List getParameters(); + + public AccessModifier getAccessModifier(); + + interface Parameter { + public String getName(); + + public Type getType(); + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/ParameterizedType.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/ParameterizedType.java new file mode 100644 index 0000000000..1e800acaa9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/ParameterizedType.java @@ -0,0 +1,18 @@ +/* + * 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.controller.sal.binding.model.api; + +/** + * Represents an instance of simple parametrized type such as List. + */ +public interface ParameterizedType extends Type { + + Type[] getActualTypeArguments(); + + Type getRawType(); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Type.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Type.java new file mode 100644 index 0000000000..1ec3c9fab2 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/Type.java @@ -0,0 +1,24 @@ +/* + * 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.controller.sal.binding.model.api; + +public interface Type { + /** + * Returns name of the package that interface belongs to. + * + * @return name of the package that interface belongs to + */ + public String getPackageName(); + + /** + * Returns name of the interface. + * + * @return name of the interface. + */ + public String getName(); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/package-info.java new file mode 100644 index 0000000000..d969a6fb9f --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.binding.model.api; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/ConstantBuilder.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/ConstantBuilder.java new file mode 100644 index 0000000000..1a16f86439 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/ConstantBuilder.java @@ -0,0 +1,22 @@ +/* + * 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.controller.sal.binding.model.api.type.builder; + +import org.opendaylight.controller.sal.binding.model.api.Constant; +import org.opendaylight.controller.sal.binding.model.api.Type; + +/** + + * + */ +public interface ConstantBuilder { + + public void assignValue(final Object value); + + public Constant toInstance(Type definingType); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/EnumBuilder.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/EnumBuilder.java new file mode 100644 index 0000000000..e9c077effd --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/EnumBuilder.java @@ -0,0 +1,22 @@ +/* + * 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.controller.sal.binding.model.api.type.builder; + +import org.opendaylight.controller.sal.binding.model.api.Enumeration; +import org.opendaylight.controller.sal.binding.model.api.Type; + +/** + + * + */ +public interface EnumBuilder { + + public void addValue(final String name, final Integer value); + + public Enumeration toInstance(final Type definingType); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedPropertyBuilder.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedPropertyBuilder.java new file mode 100644 index 0000000000..c01e740231 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedPropertyBuilder.java @@ -0,0 +1,33 @@ +/* + * 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.controller.sal.binding.model.api.type.builder; + +import org.opendaylight.controller.sal.binding.model.api.AccessModifier; +import org.opendaylight.controller.sal.binding.model.api.GeneratedProperty; +import org.opendaylight.controller.sal.binding.model.api.Type; + +/** + + * + */ +public interface GeneratedPropertyBuilder { + + public String getName(); + + public boolean addReturnType(final Type returnType); + + public void accessorModifier(final AccessModifier modifier); + + public void addComment(final String comment); + + public void setFinal(final boolean isFinal); + + public void setReadOnly(final boolean isReadOnly); + + public GeneratedProperty toInstance(final Type definingType); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedTOBuilder.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedTOBuilder.java new file mode 100644 index 0000000000..ff55fe5f12 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedTOBuilder.java @@ -0,0 +1,30 @@ +/* + * 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.controller.sal.binding.model.api.type.builder; + +import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject; +import org.opendaylight.controller.sal.binding.model.api.Type; + +/** + + * + */ +public interface GeneratedTOBuilder extends Type { + + public EnumBuilder addEnumeration(final String name); + + public GeneratedPropertyBuilder addProperty(final String name); + + public boolean addEqualsIdentity(final GeneratedPropertyBuilder property); + + public boolean addHashIdentity(final GeneratedPropertyBuilder property); + + public boolean addToStringProperty(final GeneratedPropertyBuilder property); + + public GeneratedTransferObject toInstance(); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedTypeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedTypeBuilder.java new file mode 100644 index 0000000000..6b21250ac1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/GeneratedTypeBuilder.java @@ -0,0 +1,31 @@ +/* + * 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.controller.sal.binding.model.api.type.builder; + +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; +import org.opendaylight.controller.sal.binding.model.api.Type; + +/** + + * + */ +public interface GeneratedTypeBuilder extends Type { + + public Type getParentType(); + + public void addComment(final String comment); + + public ConstantBuilder addConstant(final Type type, final String name, + final Object value); + + public EnumBuilder addEnumeration(final String name); + + public MethodSignatureBuilder addMethod(final String name); + + public GeneratedType toInstance(); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/MethodSignatureBuilder.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/MethodSignatureBuilder.java new file mode 100644 index 0000000000..349a342710 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/MethodSignatureBuilder.java @@ -0,0 +1,23 @@ +/** + + * + * March 2013 + * + * Copyright (c) 2013 by Cisco Systems, Inc. + * All rights reserved. + */ +package org.opendaylight.controller.sal.binding.model.api.type.builder; + +import org.opendaylight.controller.sal.binding.model.api.MethodSignature; +import org.opendaylight.controller.sal.binding.model.api.Type; + +public interface MethodSignatureBuilder { + + public void addReturnType(final Type returnType); + + public void addParameter(final Type type, final String name); + + public void addComment(final String comment); + + public MethodSignature toInstance(final Type definingType); +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/package-info.java new file mode 100644 index 0000000000..ff2c06e757 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/builder/package-info.java @@ -0,0 +1,9 @@ +/** + + * + * March 2013 + * + * Copyright (c) 2013 by Cisco Systems, Inc. + * All rights reserved. + */ +package org.opendaylight.controller.sal.binding.model.api.type.builder; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/provider/package-info.java b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/provider/package-info.java new file mode 100644 index 0000000000..6fcb1a82ca --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-model-api/src/main/java/org/opendaylight/controller/sal/binding/model/api/type/provider/package-info.java @@ -0,0 +1,9 @@ +/** + + * + * March 2013 + * + * Copyright (c) 2013 by Cisco Systems, Inc. + * All rights reserved. + */ +package org.opendaylight.controller.sal.binding.model.api.type.provider; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/pom.xml b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/pom.xml new file mode 100644 index 0000000000..dfa23fae72 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/pom.xml @@ -0,0 +1,62 @@ + + 4.0.0 + + org.opendaylight.controller + binding-generator + 1.0 + + code-generator-demo + + + + org.antlr + antlr4 + 4.0 + + + org.opendaylight.controller + binding-generator-impl + 1.0 + + + org.opendaylight.controller + yang-model-parser-impl + 1.0 + + + org.opendaylight.controller + binding-java-api-generator + 1.0 + + + + + + + maven-assembly-plugin + 2.4 + + + jar-with-dependencies + + + + org.opendaylight.controller.yang.Demo + + + + + + make-assembly + package + + single + + + + + + + + + diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/java/org/opendaylight/controller/Demo.java b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/java/org/opendaylight/controller/Demo.java new file mode 100644 index 0000000000..bba11f5de8 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/java/org/opendaylight/controller/Demo.java @@ -0,0 +1,50 @@ +/** + + * + * March 2013 + * + * Copyright (c) 2013 by Cisco Systems, Inc. + * All rights reserved. + */ +package org.opendaylight.controller; + +import java.io.File; +import java.util.Map; + +import org.opendaylight.controller.model.parser.builder.YangModelBuilder; + + + +public class Demo { + + public static void main(String[] args) throws Exception { + + String yangFilesDir; + if(args.length > 0) { + yangFilesDir = args[0]; + } else { + yangFilesDir = "src/main/resources"; + } + + File resourceDir = new File(yangFilesDir); + if(!resourceDir.exists()) { + throw new IllegalArgumentException("Specified resource directory does not exists: "+ resourceDir.getAbsolutePath()); + } + + String[] dirList = resourceDir.list(); + String[] absFiles = new String[dirList.length]; + + int i = 0; + for(String fileName : dirList) { + File f = new File(fileName); + absFiles[i] = f.getAbsolutePath(); + i++; + } + + YangModelBuilder builder = new YangModelBuilder(absFiles); + Map builtModules = builder.build(); + + System.out.println("Modules built: "+ builtModules.size()); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo-topology.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo-topology.yang new file mode 100644 index 0000000000..23552bb2ef --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo-topology.yang @@ -0,0 +1,224 @@ +module demo-topology { + yang-version 1; + namespace "urn:demo.simple-topology"; + prefix "tp"; + import simple-list-demo { prefix "simple"; revision-date 2008-01-01; } + import controller-network {prefix "cn";} + import mount {prefix "mnt";} + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2013-02-08"{ + reference " WILL BE DEFINED LATER"; + } + + + + + + deviation /base:system/base:user/base:type { + deviate add { + default "admin"; // new users are 'admin' by default + } + } + + deviation /base:system/base:name-server { + deviate replace { + max-elements 3; + } + } + + deviation "/base:system" { + deviate delete { + must "daytime or time"; + } + } + + + + + + + grouping target { + status "current"; + leaf address { + type inet:ip-address; + description "Target IP address"; + } + leaf port { + type inet:port-number; + description "Target port number"; + } + } + + augment "/cn:network/cn:topologies/cn:topology" { + container prefixes { + container "prefix" { + leaf id { + type string; + + description ""; + } + + leaf-list advertising-node-id { + type cn:node-ref; + + description ""; + } + } + } + mnt:mountpoint point { + mnt:target-ref target; + + } + } + + container peer { + container destination { + uses target; + } + } + + container topology { + + leaf ifType { + type enumeration { + enum ethernet; + enum atm; + } + } + leaf ifMTU { + type uint32; + } + must "ifType != 'ethernet' or " + + "(ifType = 'ethernet' and ifMTU = 1500)" { + error-message "An ethernet MTU must be 1500"; + } + + presence "test-presence"; + + description " + This is the model of abstract topology which contains only Network + Nodes and Network Links. Each topology MUST be identified by + unique topology-id for reason that the store could contain many + topologies. + "; + + leaf topology-id { + type string; + description " + It is presumed that datastore will contain many topologies. To + distinguish between topologies it is vital to have UNIQUE + topology identifier. + "; + } + + container network-nodes { + list network-node { + ordered-by system; + description "The list of network nodes defined for topology."; + + key "node-id"; + + leaf node-id { + type string; + description "The Topology identifier of network-node."; + } + + list network-interface { + key "interface-id"; + + leaf interface-id { + type uint8; + } + + leaf interface-address { + type string; + } + } + + container node-attributes { + description " + Additional attributes that can Network Node contains. + "; + + leaf geo-latitude { + type decimal64 { + fraction-digits 2; + } + config true; + } + + leaf geo-longitude { + type decimal64 { + fraction-digits 2; + } + config true; + } + } + } + } + + container network-links { + list network-link { + description " + The Network Link which is defined by Local (Source) and + Remote (Destination) Network Nodes. Every link MUST be + defined either by identifier and his local and remote + Network Nodes (in real applications it is common that many + links are originated from one node and end up in same + remote node). To ensure that we would always know to + distinguish between links, every link SHOULD have + identifier. + "; + key "link-id"; + + leaf link-id { + type string; + description ""; + } + + container source { + leaf node-id { + type string; + description "Source node identifier."; + } + } + + container destination { + leaf node-id { + type string; + description "Destination node identifier."; + } + } + + container link-attributes { + description "Aditional attributes that can Network Link contains."; + } + } + } + } + + rpc activate-software-image { + input { + leaf image-name { + type string; + } + } + output { + leaf status { + type string; + } + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types1.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types1.yang new file mode 100644 index 0000000000..102529858b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types1.yang @@ -0,0 +1,80 @@ +module types1 { + yang-version 1; + namespace "urn:simple.container.demo"; + prefix "t1"; + + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + + leaf mybits { + type bits { + bit disable-nagle { + position 0; + } + bit auto-sense-speed { + position 1; + } + bit 10-Mb-only { + position 2; + } + } + default "auto-sense-speed"; + } + + container interfaces { + list ifEntry { + key "ifIndex"; + + leaf ifIndex { + type uint32; + } + leaf ifDescr { + type string; + } + leaf ifType { + type uint8; + } + leaf ifMtu { + type int32; + } + } + } + + + container topology { + leaf name { + type string; + } + } + + + + + + + +// typedef my-string { +// type string { +// length "0..4"; +// pattern "[0-9a-fA-F]*"; +// } +// } + + +// leaf completed { +// type types2:percent; +// } + +// leaf testleaf { +// type data:my-base-int32-type; +// } + +// leaf-list domain-search { +// type string; +// description "List of domain names to search"; +// } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types2.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types2.yang new file mode 100644 index 0000000000..a056bdb2e9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types2.yang @@ -0,0 +1,35 @@ +module types2 { + yang-version 1; + namespace "urn:simple.types.data.demo"; + prefix "t2"; + + import types1 { + prefix "t1"; + } + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description "This is types-data test description"; + + revision "2013-02-27" { + reference " WILL BE DEFINED LATER"; + } + + + augment "/t1:interfaces/t1:ifEntry" { + when "t1:ifType='ds0'"; + leaf ds0ChannelNumber { + type string; + } + } + + typedef my-leaf-ref { + type leafref { + path "/t1:topology/t1:name"; + } + description "This type is used for leafs that reference network node instance."; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types3.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types3.yang new file mode 100644 index 0000000000..0d09259f3e --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types3.yang @@ -0,0 +1,35 @@ +module types3 { + yang-version 1; + namespace "urn:simple.types3.data.demo"; + prefix "scd"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description "This is types-data test description"; + + revision "2013-02-27" { + reference " WILL BE DEFINED LATER"; + } + + typedef my-decimal { + type decimal64 { + fraction-digits 2; + } + } + + typedef my-base-int32-type { + type int32 { + range "0..32"; + } + } + + typedef percent { + type uint8 { + range "0 .. 100"; + } + description "Percentage"; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/test-topology.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/test-topology.yang new file mode 100644 index 0000000000..76582c7cda --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/test-topology.yang @@ -0,0 +1,123 @@ +// vi: set smarttab sw=4 tabstop=4: +module abstract-topology { + yang-version 1; + namespace "pre:simple.test.demo"; + prefix "tp"; + + import ietf-inet-types { prefix "inet"; } + import abstract-prefixes { prefix "abs-pref"; } + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description " + This module contains the definitions of elements that creates network + topology i.e. definition of network nodes and links. This module is + not designed to be used solely for network representation. This module + SHOULD be used as base module in defining the network topology. + "; + + revision "2012-02-08" { + reference " WILL BE DEFINED LATER"; + } + + typedef topology-id-ref { + type leafref { + path "/tp:topology/tp:topology-id"; + } + description "This type is used for leafs that reference topology identifier instance."; + } + + typedef network-node-id-ref { + type leafref { + path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id"; + } + description "This type is used for leafs that reference network node instance."; + } + + typedef link-id-ref { + type leafref { + path "/tp:topology/tp:network-links/tp:network-link/tp:link-id"; + } + description "This type is used for leafs that reference network link instance."; + } + + container topology { + description " + This is the model of abstract topology which contains only Network + Nodes and Network Links. Each topology MUST be identified by + unique topology-id for reason that the store could contain many + topologies. + "; + + leaf topology-id { + type inet:uri; + description " + It is presumed that datastore will contain many topologies. To + distinguish between topologies it is vital to have UNIQUE + topology identifier. + "; + } + + container network-nodes { + list network-node { + description "The list of network nodes defined for topology."; + + key "node-id"; + + leaf node-id { + type inet:uri; + description "The Topology identifier of network-node."; + } + + container attributes { + description " + Additional attributes that can Network Node contains. + "; + } + } + } + + container network-links { + list network-link { + description " + The Network Link which is defined by Local (Source) and + Remote (Destination) Network Nodes. Every link MUST be + defined either by identifier and his local and remote + Network Nodes (in real applications it is common that many + links are originated from one node and end up in same + remote node). To ensure that we would always know to + distinguish between links, every link SHOULD have + identifier. + "; + key "link-id"; + + leaf link-id { + type inet:uri; + description ""; + } + + container source { + leaf node-id { + type node-id-ref; + description "Source node identifier."; + } + } + + container destination { + leaf node-id { + type node-id-ref; + description "Destination node identifier."; + } + } + + container attributes { + description "Aditional attributes that can Network Link contains."; + } + } + } + } + + //TODO: add base operations +} diff --git a/opendaylight/sal/yang-prototype/code-generator/pom.xml b/opendaylight/sal/yang-prototype/code-generator/pom.xml new file mode 100644 index 0000000000..add22412cb --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/pom.xml @@ -0,0 +1,96 @@ + + 4.0.0 + org.opendaylight.controller + binding-generator + 1.0 + pom + binding-generator + + + UTF-8 + + + + ../yang + ../sal/sal-schema-repository-api + code-generator-demo + yang-model-parser-api + yang-model-parser-impl + binding-model-api + binding-generator-api + binding-generator-spi + binding-generator-util + binding-generator-impl + binding-java-api-generator + + + + + junit + junit + 4.10 + test + true + + + org.slf4j + slf4j-api + 1.7.2 + + + org.slf4j + slf4j-simple + 1.7.2 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0 + true + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + maven + + + + + aggregate + + site + + + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 2.4.0 + + Max + Low + site + + + + org.codehaus.mojo + jdepend-maven-plugin + 2.0-beta-2 + + + + diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml new file mode 100644 index 0000000000..184abf03ee --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + + org.opendaylight.controller + binding-generator + 1.0 + + yang-model-parser-impl + + + + org.opendaylight.controller + yang-common + 1.0 + + + org.opendaylight.controller + yang-model-api + 1.0 + + + org.opendaylight.controller + yang-model-util + 1.0 + + + org.opendaylight.controller + binding-model-api + 1.0 + + + + org.antlr + antlr4 + 4.0 + + + org.slf4j + slf4j-api + 1.7.2 + + + org.slf4j + slf4j-simple + 1.7.2 + + + org.mockito + mockito-all + 1.8.4 + + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangLexer.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangLexer.java new file mode 100644 index 0000000000..0fbfc1c6bd --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangLexer.java @@ -0,0 +1,1379 @@ +/* + * 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.controller.antlrv4.code.gen; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.RuleContext; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNSimulator; +import org.antlr.v4.runtime.atn.LexerATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; +import org.antlr.v4.runtime.dfa.DFA; + +@SuppressWarnings({ "all", "warnings", "unchecked", "unused", "cast" }) +public class YangLexer extends Lexer { + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); + public static final int SEMICOLON = 1, LEFT_BRACE = 2, RIGHT_BRACE = 3, + PLUS = 4, WS = 5, LINE_COMMENT = 6, BLOCK_COMMENT = 7, + YIN_ELEMENT_KEYWORD = 8, YANG_VERSION_KEYWORD = 9, + WHEN_KEYWORD = 10, VALUE_KEYWORD = 11, USES_KEYWORD = 12, + UNITS_KEYWORD = 13, UNIQUE_KEYWORD = 14, TYPEDEF_KEYWORD = 15, + TYPE_KEYWORD = 16, SUBMODULE_KEYWORD = 17, STATUS_KEYWORD = 18, + RPC_KEYWORD = 19, REVISION_DATE_KEYWORD = 20, + REVISION_KEYWORD = 21, REQUIRE_INSTANCE_KEYWORD = 22, + REFINE_KEYWORD = 23, REFERENCE_KEYWORD = 24, RANGE_KEYWORD = 25, + PRESENCE_KEYWORD = 26, PREFIX_KEYWORD = 27, POSITION_KEYWORD = 28, + PATTERN_KEYWORD = 29, PATH_KEYWORD = 30, OUTPUT_KEYWORD = 31, + ORGANIZATION_KEYWORD = 32, ORDERED_BY_KEYWORD = 33, + NOTIFICATION_KEYWORD = 34, NAMESPACE_KEYWORD = 35, + MUST_KEYWORD = 36, MODULE_KEYWORD = 37, MIN_ELEMENTS_KEYWORD = 38, + MAX_ELEMENTS_KEYWORD = 39, MANDATORY_KEYWORD = 40, + LIST_KEYWORD = 41, LENGTH_KEYWORD = 42, LEAF_LIST_KEYWORD = 43, + LEAF_KEYWORD = 44, KEY_KEYWORD = 45, INPUT_KEYWORD = 46, + INCLUDE_KEYWORD = 47, IMPORT_KEYWORD = 48, IF_FEATURE_KEYWORD = 49, + IDENTITY_KEYWORD = 50, GROUPING_KEYWORD = 51, + FRACTION_DIGITS_KEYWORD = 52, FEATURE_KEYWORD = 53, + DEVIATE_KEYWORD = 54, DEVIATION_KEYWORD = 55, + EXTENSION_KEYWORD = 56, ERROR_MESSAGE_KEYWORD = 57, + ERROR_APP_TAG_KEYWORD = 58, ENUM_KEYWORD = 59, + DESCRIPTION_KEYWORD = 60, DEFAULT_KEYWORD = 61, + CONTAINER_KEYWORD = 62, CONTACT_KEYWORD = 63, CONFIG_KEYWORD = 64, + CHOICE_KEYWORD = 65, CASE_KEYWORD = 66, BIT_KEYWORD = 67, + BELONGS_TO_KEYWORD = 68, BASE_KEYWORD = 69, AUGMENT_KEYWORD = 70, + ARGUMENT_KEYWORD = 71, ANYXML_KEYWORD = 72, IDENTIFIER = 73, + STRING = 74, S = 75; + public static final int VALUE_MODE = 1; + public static String[] modeNames = { "DEFAULT_MODE", "VALUE_MODE" }; + + public static final String[] tokenNames = { "", "SEMICOLON", + "LEFT_BRACE", "'}'", "'+'", "WS", "LINE_COMMENT", "BLOCK_COMMENT", + "'yin-element'", "'yang-version'", "'when'", "'value'", "'uses'", + "'units'", "'unique'", "'typedef'", "'type'", "'submodule'", + "'status'", "'rpc'", "'revision-date'", "'revision'", + "'require-instance'", "'refine'", "'reference'", "'range'", + "'presence'", "'prefix'", "'position'", "'pattern'", "'path'", + "'output'", "'organization'", "'ordered-by'", "'notification'", + "'namespace'", "'must'", "'module'", "'min-elements'", + "'max-elements'", "'mandatory'", "'list'", "'length'", + "'leaf-list'", "'leaf'", "'key'", "'input'", "'include'", + "'import'", "'if-feature'", "'identity'", "'grouping'", + "'fraction-digits'", "'feature'", "'deviate'", "'deviation'", + "'extension'", "'error-message'", "'error-app-tag'", "'enum'", + "'description'", "'default'", "'container'", "'contact'", + "'config'", "'choice'", "'case'", "'bit'", "'belongs-to'", + "'base'", "'augment'", "'argument'", "'anyxml'", "IDENTIFIER", + "STRING", "S" }; + public static final String[] ruleNames = { "PLUS", "WS", "LINE_COMMENT", + "BLOCK_COMMENT", "SEMICOLON", "LEFT_BRACE", "RIGHT_BRACE", + "YIN_ELEMENT_KEYWORD", "YANG_VERSION_KEYWORD", "WHEN_KEYWORD", + "VALUE_KEYWORD", "USES_KEYWORD", "UNITS_KEYWORD", "UNIQUE_KEYWORD", + "TYPEDEF_KEYWORD", "TYPE_KEYWORD", "SUBMODULE_KEYWORD", + "STATUS_KEYWORD", "RPC_KEYWORD", "REVISION_DATE_KEYWORD", + "REVISION_KEYWORD", "REQUIRE_INSTANCE_KEYWORD", "REFINE_KEYWORD", + "REFERENCE_KEYWORD", "RANGE_KEYWORD", "PRESENCE_KEYWORD", + "PREFIX_KEYWORD", "POSITION_KEYWORD", "PATTERN_KEYWORD", + "PATH_KEYWORD", "OUTPUT_KEYWORD", "ORGANIZATION_KEYWORD", + "ORDERED_BY_KEYWORD", "NOTIFICATION_KEYWORD", "NAMESPACE_KEYWORD", + "MUST_KEYWORD", "MODULE_KEYWORD", "MIN_ELEMENTS_KEYWORD", + "MAX_ELEMENTS_KEYWORD", "MANDATORY_KEYWORD", "LIST_KEYWORD", + "LENGTH_KEYWORD", "LEAF_LIST_KEYWORD", "LEAF_KEYWORD", + "KEY_KEYWORD", "INPUT_KEYWORD", "INCLUDE_KEYWORD", + "IMPORT_KEYWORD", "IF_FEATURE_KEYWORD", "IDENTITY_KEYWORD", + "GROUPING_KEYWORD", "FRACTION_DIGITS_KEYWORD", "FEATURE_KEYWORD", + "DEVIATE_KEYWORD", "DEVIATION_KEYWORD", "EXTENSION_KEYWORD", + "ERROR_MESSAGE_KEYWORD", "ERROR_APP_TAG_KEYWORD", "ENUM_KEYWORD", + "DESCRIPTION_KEYWORD", "DEFAULT_KEYWORD", "CONTAINER_KEYWORD", + "CONTACT_KEYWORD", "CONFIG_KEYWORD", "CHOICE_KEYWORD", + "CASE_KEYWORD", "BIT_KEYWORD", "BELONGS_TO_KEYWORD", + "BASE_KEYWORD", "AUGMENT_KEYWORD", "ARGUMENT_KEYWORD", + "ANYXML_KEYWORD", "IDENTIFIER", "ESC", "UNICODE", "HEX", + "END_IDENTIFIER_SEMICOLON", "END_IDENTIFIER_LEFT_BRACE", + "SUB_STRING", "STRING", "S" }; + + public YangLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this, _ATN, _decisionToDFA, + _sharedContextCache); + } + + @Override + public String getGrammarFileName() { + return "yangLexer.g4"; + } + + @Override + public String[] getTokenNames() { + return tokenNames; + } + + @Override + public String[] getRuleNames() { + return ruleNames; + } + + @Override + public String[] getModeNames() { + return modeNames; + } + + @Override + public ATN getATN() { + return _ATN; + } + + @Override + public void action(RuleContext _localctx, int ruleIndex, int actionIndex) { + switch (ruleIndex) { + case 0: + PLUS_action((RuleContext) _localctx, actionIndex); + break; + + case 1: + WS_action((RuleContext) _localctx, actionIndex); + break; + + case 2: + LINE_COMMENT_action((RuleContext) _localctx, actionIndex); + break; + + case 3: + BLOCK_COMMENT_action((RuleContext) _localctx, actionIndex); + break; + + case 4: + SEMICOLON_action((RuleContext) _localctx, actionIndex); + break; + + case 5: + LEFT_BRACE_action((RuleContext) _localctx, actionIndex); + break; + + case 6: + RIGHT_BRACE_action((RuleContext) _localctx, actionIndex); + break; + + case 7: + YIN_ELEMENT_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 8: + YANG_VERSION_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 9: + WHEN_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 10: + VALUE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 11: + USES_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 12: + UNITS_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 13: + UNIQUE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 14: + TYPEDEF_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 15: + TYPE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 16: + SUBMODULE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 17: + STATUS_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 18: + RPC_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 19: + REVISION_DATE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 20: + REVISION_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 21: + REQUIRE_INSTANCE_KEYWORD_action((RuleContext) _localctx, + actionIndex); + break; + + case 22: + REFINE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 23: + REFERENCE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 24: + RANGE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 25: + PRESENCE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 26: + PREFIX_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 27: + POSITION_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 28: + PATTERN_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 29: + PATH_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 31: + ORGANIZATION_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 32: + ORDERED_BY_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 33: + NOTIFICATION_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 34: + NAMESPACE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 35: + MUST_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 36: + MODULE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 37: + MIN_ELEMENTS_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 38: + MAX_ELEMENTS_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 39: + MANDATORY_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 40: + LIST_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 41: + LENGTH_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 42: + LEAF_LIST_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 43: + LEAF_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 44: + KEY_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 46: + INCLUDE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 47: + IMPORT_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 48: + IF_FEATURE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 49: + IDENTITY_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 50: + GROUPING_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 51: + FRACTION_DIGITS_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 52: + FEATURE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 53: + DEVIATE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 54: + DEVIATION_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 55: + EXTENSION_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 56: + ERROR_MESSAGE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 57: + ERROR_APP_TAG_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 58: + ENUM_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 59: + DESCRIPTION_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 60: + DEFAULT_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 61: + CONTAINER_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 62: + CONTACT_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 63: + CONFIG_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 64: + CHOICE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 65: + CASE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 66: + BIT_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 67: + BELONGS_TO_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 68: + BASE_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 69: + AUGMENT_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 70: + ARGUMENT_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 71: + ANYXML_KEYWORD_action((RuleContext) _localctx, actionIndex); + break; + + case 72: + IDENTIFIER_action((RuleContext) _localctx, actionIndex); + break; + + case 76: + END_IDENTIFIER_SEMICOLON_action((RuleContext) _localctx, + actionIndex); + break; + + case 77: + END_IDENTIFIER_LEFT_BRACE_action((RuleContext) _localctx, + actionIndex); + break; + + case 79: + STRING_action((RuleContext) _localctx, actionIndex); + break; + + case 80: + S_action((RuleContext) _localctx, actionIndex); + break; + } + } + + private void CHOICE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 62: + pushMode(VALUE_MODE); + break; + } + } + + private void YIN_ELEMENT_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 7: + pushMode(VALUE_MODE); + break; + } + } + + private void WHEN_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 9: + pushMode(VALUE_MODE); + break; + } + } + + private void REVISION_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 20: + pushMode(VALUE_MODE); + break; + } + } + + private void DESCRIPTION_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 57: + pushMode(VALUE_MODE); + break; + } + } + + private void NAMESPACE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 33: + pushMode(VALUE_MODE); + break; + } + } + + private void MODULE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 35: + pushMode(VALUE_MODE); + break; + } + } + + private void REFERENCE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 23: + pushMode(VALUE_MODE); + break; + } + } + + private void CONTACT_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 60: + pushMode(VALUE_MODE); + break; + } + } + + private void LEAF_LIST_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 41: + pushMode(VALUE_MODE); + break; + } + } + + private void REVISION_DATE_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 19: + pushMode(VALUE_MODE); + break; + } + } + + private void BELONGS_TO_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 65: + pushMode(VALUE_MODE); + break; + } + } + + private void LEAF_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 42: + pushMode(VALUE_MODE); + break; + } + } + + private void PREFIX_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 26: + pushMode(VALUE_MODE); + break; + } + } + + private void DEFAULT_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 58: + pushMode(VALUE_MODE); + break; + } + } + + private void PRESENCE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 25: + pushMode(VALUE_MODE); + break; + } + } + + private void ARGUMENT_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 68: + pushMode(VALUE_MODE); + break; + } + } + + private void NOTIFICATION_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 32: + pushMode(VALUE_MODE); + break; + } + } + + private void RPC_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 18: + pushMode(VALUE_MODE); + break; + } + } + + private void CONTAINER_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 59: + pushMode(VALUE_MODE); + break; + } + } + + private void DEVIATION_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 52: + pushMode(VALUE_MODE); + break; + } + } + + private void STATUS_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 17: + pushMode(VALUE_MODE); + break; + } + } + + private void IDENTITY_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 47: + pushMode(VALUE_MODE); + break; + } + } + + private void IDENTIFIER_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 70: + pushMode(VALUE_MODE); + break; + } + } + + private void REFINE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 22: + pushMode(VALUE_MODE); + break; + } + } + + private void USES_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 11: + pushMode(VALUE_MODE); + break; + } + } + + private void VALUE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 10: + pushMode(VALUE_MODE); + break; + } + } + + private void IMPORT_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 45: + pushMode(VALUE_MODE); + break; + } + } + + private void BLOCK_COMMENT_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 3: + skip(); + break; + } + } + + private void PLUS_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 0: + pushMode(VALUE_MODE); + break; + } + } + + private void PATTERN_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 28: + pushMode(VALUE_MODE); + break; + } + } + + private void IF_FEATURE_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 46: + pushMode(VALUE_MODE); + break; + } + } + + private void LENGTH_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 40: + pushMode(VALUE_MODE); + break; + } + } + + private void FEATURE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 50: + pushMode(VALUE_MODE); + break; + } + } + + private void REQUIRE_INSTANCE_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 21: + pushMode(VALUE_MODE); + break; + } + } + + private void ORGANIZATION_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 30: + pushMode(VALUE_MODE); + break; + } + } + + private void UNIQUE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 13: + pushMode(VALUE_MODE); + break; + } + } + + private void SUBMODULE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 16: + pushMode(VALUE_MODE); + break; + } + } + + private void TYPE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 15: + pushMode(VALUE_MODE); + break; + } + } + + private void RIGHT_BRACE_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 6: + _type = RIGHT_BRACE; + break; + } + } + + private void ERROR_MESSAGE_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 54: + pushMode(VALUE_MODE); + break; + } + } + + private void LINE_COMMENT_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 2: + skip(); + break; + } + } + + private void END_IDENTIFIER_LEFT_BRACE_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 72: + _type = LEFT_BRACE; + popMode(); + break; + } + } + + private void MIN_ELEMENTS_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 36: + pushMode(VALUE_MODE); + break; + } + } + + private void MUST_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 34: + pushMode(VALUE_MODE); + break; + } + } + + private void SEMICOLON_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 4: + _type = SEMICOLON; + break; + } + } + + private void POSITION_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 27: + pushMode(VALUE_MODE); + break; + } + } + + private void PATH_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 29: + pushMode(VALUE_MODE); + break; + } + } + + private void S_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 74: + skip(); + break; + } + } + + private void KEY_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 43: + pushMode(VALUE_MODE); + break; + } + } + + private void EXTENSION_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 53: + pushMode(VALUE_MODE); + break; + } + } + + private void WS_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 1: + skip(); + break; + } + } + + private void MANDATORY_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 38: + pushMode(VALUE_MODE); + break; + } + } + + private void ORDERED_BY_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 31: + pushMode(VALUE_MODE); + break; + } + } + + private void ERROR_APP_TAG_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 55: + pushMode(VALUE_MODE); + break; + } + } + + private void INCLUDE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 44: + pushMode(VALUE_MODE); + break; + } + } + + private void END_IDENTIFIER_SEMICOLON_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 71: + _type = SEMICOLON; + popMode(); + break; + } + } + + private void ANYXML_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 69: + pushMode(VALUE_MODE); + break; + } + } + + private void AUGMENT_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 67: + pushMode(VALUE_MODE); + break; + } + } + + private void DEVIATE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 51: + pushMode(VALUE_MODE); + break; + } + } + + private void LEFT_BRACE_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 5: + _type = LEFT_BRACE; + break; + } + } + + private void YANG_VERSION_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 8: + pushMode(VALUE_MODE); + break; + } + } + + private void LIST_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 39: + pushMode(VALUE_MODE); + break; + } + } + + private void TYPEDEF_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 14: + pushMode(VALUE_MODE); + break; + } + } + + private void MAX_ELEMENTS_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 37: + pushMode(VALUE_MODE); + break; + } + } + + private void ENUM_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 56: + pushMode(VALUE_MODE); + break; + } + } + + private void CASE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 63: + pushMode(VALUE_MODE); + break; + } + } + + private void UNITS_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 12: + pushMode(VALUE_MODE); + break; + } + } + + private void GROUPING_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 48: + pushMode(VALUE_MODE); + break; + } + } + + private void BASE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 66: + pushMode(VALUE_MODE); + break; + } + } + + private void RANGE_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 24: + pushMode(VALUE_MODE); + break; + } + } + + private void FRACTION_DIGITS_KEYWORD_action(RuleContext _localctx, + int actionIndex) { + switch (actionIndex) { + case 49: + pushMode(VALUE_MODE); + break; + } + } + + private void CONFIG_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 61: + pushMode(VALUE_MODE); + break; + } + } + + private void BIT_KEYWORD_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 64: + pushMode(VALUE_MODE); + break; + } + } + + private void STRING_action(RuleContext _localctx, int actionIndex) { + switch (actionIndex) { + case 73: + popMode(); + break; + } + } + + public static final String _serializedATN = "\2\4M\u03bf\b\1\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4" + + "\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4" + + "\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4" + + "\27\t\27\4\30\t\30\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4" + + "\36\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'" + + "\4(\t(\4)\t)\4*\t*\4+\t+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4" + + "\62\t\62\4\63\t\63\4\64\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t" + + "9\4:\t:\4;\t;\4<\t<\4=\t=\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4" + + "E\tE\4F\tF\4G\tG\4H\tH\4I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\t" + + "P\4Q\tQ\4R\tR\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\7\4\u00b3" + + "\n\4\f\4\16\4\u00b6\13\4\3\4\3\4\3\5\3\5\3\5\3\5\7\5\u00be\n\5\f\5\16" + + "\5\u00c1\13\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\b" + + "\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3" + + "\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3" + + "\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3" + + "\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17" + + "\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20" + + "\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22" + + "\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23" + + "\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25" + + "\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26" + + "\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27" + + "\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30" + + "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31" + + "\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\33" + + "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\34\3\34" + + "\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35" + + "\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37" + + "\3\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3!\3!\3" + + "!\3!\3!\3!\3!\3!\3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"" + + "\3\"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3$\3" + + "$\3$\3$\3$\3$\3$\3%\3%\3%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3\'\3" + + "\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3(\3(\3(\3(\3(" + + "\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3*" + + "\3*\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3+\3+\3+\3+\3,\3,\3,\3,\3,\3,\3,\3," + + "\3,\3,\3,\3,\3-\3-\3-\3-\3-\3-\3-\3.\3.\3.\3.\3.\3.\3/\3/\3/\3/\3/\3/" + + "\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\61\3\61\3\61\3\61" + + "\3\61\3\61\3\61\3\61\3\61\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3\62\3\62" + + "\3\62\3\62\3\62\3\62\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\63" + + "\3\63\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\65\3\65" + + "\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65" + + "\3\65\3\65\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\67\3\67" + + "\3\67\3\67\3\67\3\67\3\67\3\67\3\67\3\67\38\38\38\38\38\38\38\38\38\3" + + "8\38\38\39\39\39\39\39\39\39\39\39\39\39\39\3:\3:\3:\3:\3:\3:\3:\3:\3" + + ":\3:\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3" + + ";\3<\3<\3<\3<\3<\3<\3<\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3>\3" + + ">\3>\3>\3>\3>\3>\3>\3>\3>\3?\3?\3?\3?\3?\3?\3?\3?\3?\3?\3?\3?\3@\3@\3" + + "@\3@\3@\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B\3" + + "B\3B\3B\3C\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3" + + "E\3E\3E\3E\3E\3E\3F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3" + + "H\3H\3H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3I\3I\3J\3J\7J\u0382" + + "\nJ\fJ\16J\u0385\13J\3J\3J\3K\3K\3K\5K\u038c\nK\3L\3L\3L\3L\3L\3L\3M\3" + + "M\3N\3N\3N\3N\3O\3O\3O\3O\3P\3P\3P\7P\u03a1\nP\fP\16P\u03a4\13P\3P\3P" + + "\3P\3P\7P\u03aa\nP\fP\16P\u03ad\13P\3P\5P\u03b0\nP\3Q\3Q\6Q\u03b4\nQ\r" + + "Q\16Q\u03b5\5Q\u03b8\nQ\3Q\3Q\3R\3R\3R\3R\2S\4\6\2\6\7\3\b\b\4\n\t\5\f" + + "\3\6\16\4\7\20\5\b\22\n\t\24\13\n\26\f\13\30\r\f\32\16\r\34\17\16\36\20" + + "\17 \21\20\"\22\21$\23\22&\24\23(\25\24*\26\25,\27\26.\30\27\60\31\30" + + "\62\32\31\64\33\32\66\34\338\35\34:\36\35<\37\36> \37@!\1B\" D#!F$\"H" + + "%#J&$L\'%N(&P)\'R*(T+)V,*X-+Z.,\\/-^\60\1`\61.b\62/d\63\60f\64\61h\65" + + "\62j\66\63l\67\64n8\65p9\66r:\67t;8v<9x=:z>;|?<~@=\u0080A>\u0082B?\u0084" + + "C@\u0086DA\u0088EB\u008aFC\u008cGD\u008eHE\u0090IF\u0092JG\u0094KH\u0096" + + "\2\1\u0098\2\1\u009a\2\1\u009c\2I\u009e\2J\u00a0\2\1\u00a2LK\u00a4ML\4" + + "\2\3\r\5\13\f\17\17\"\"\4\f\f\17\17\2\6/;C\\aac|\7/\60\62\3\2\2\2\2@\3\2\2\2\2B\3\2\2\2\2D\3\2\2\2\2F\3\2\2\2\2H" + + "\3\2\2\2\2J\3\2\2\2\2L\3\2\2\2\2N\3\2\2\2\2P\3\2\2\2\2R\3\2\2\2\2T\3\2" + + "\2\2\2V\3\2\2\2\2X\3\2\2\2\2Z\3\2\2\2\2\\\3\2\2\2\2^\3\2\2\2\2`\3\2\2" + + "\2\2b\3\2\2\2\2d\3\2\2\2\2f\3\2\2\2\2h\3\2\2\2\2j\3\2\2\2\2l\3\2\2\2\2" + + "n\3\2\2\2\2p\3\2\2\2\2r\3\2\2\2\2t\3\2\2\2\2v\3\2\2\2\2x\3\2\2\2\2z\3" + + "\2\2\2\2|\3\2\2\2\2~\3\2\2\2\2\u0080\3\2\2\2\2\u0082\3\2\2\2\2\u0084\3" + + "\2\2\2\2\u0086\3\2\2\2\2\u0088\3\2\2\2\2\u008a\3\2\2\2\2\u008c\3\2\2\2" + + "\2\u008e\3\2\2\2\2\u0090\3\2\2\2\2\u0092\3\2\2\2\2\u0094\3\2\2\2\3\u009c" + + "\3\2\2\2\3\u009e\3\2\2\2\3\u00a2\3\2\2\2\3\u00a4\3\2\2\2\4\u00a6\3\2\2" + + "\2\6\u00aa\3\2\2\2\b\u00ae\3\2\2\2\n\u00b9\3\2\2\2\f\u00c7\3\2\2\2\16" + + "\u00cb\3\2\2\2\20\u00cf\3\2\2\2\22\u00d3\3\2\2\2\24\u00e1\3\2\2\2\26\u00f0" + + "\3\2\2\2\30\u00f7\3\2\2\2\32\u00ff\3\2\2\2\34\u0106\3\2\2\2\36\u010e\3" + + "\2\2\2 \u0117\3\2\2\2\"\u0121\3\2\2\2$\u0128\3\2\2\2&\u0134\3\2\2\2(\u013d" + + "\3\2\2\2*\u0143\3\2\2\2,\u0153\3\2\2\2.\u015e\3\2\2\2\60\u0171\3\2\2\2" + + "\62\u017a\3\2\2\2\64\u0186\3\2\2\2\66\u018e\3\2\2\28\u0199\3\2\2\2:\u01a2" + + "\3\2\2\2<\u01ad\3\2\2\2>\u01b7\3\2\2\2@\u01be\3\2\2\2B\u01c5\3\2\2\2D" + + "\u01d4\3\2\2\2F\u01e1\3\2\2\2H\u01f0\3\2\2\2J\u01fc\3\2\2\2L\u0203\3\2" + + "\2\2N\u020c\3\2\2\2P\u021b\3\2\2\2R\u022a\3\2\2\2T\u0236\3\2\2\2V\u023d" + + "\3\2\2\2X\u0246\3\2\2\2Z\u0252\3\2\2\2\\\u0259\3\2\2\2^\u025f\3\2\2\2" + + "`\u0265\3\2\2\2b\u026f\3\2\2\2d\u0278\3\2\2\2f\u0285\3\2\2\2h\u0290\3" + + "\2\2\2j\u029b\3\2\2\2l\u02ad\3\2\2\2n\u02b7\3\2\2\2p\u02c1\3\2\2\2r\u02cd" + + "\3\2\2\2t\u02d9\3\2\2\2v\u02e9\3\2\2\2x\u02f9\3\2\2\2z\u0300\3\2\2\2|" + + "\u030e\3\2\2\2~\u0318\3\2\2\2\u0080\u0324\3\2\2\2\u0082\u032e\3\2\2\2" + + "\u0084\u0337\3\2\2\2\u0086\u0340\3\2\2\2\u0088\u0347\3\2\2\2\u008a\u034d" + + "\3\2\2\2\u008c\u035a\3\2\2\2\u008e\u0361\3\2\2\2\u0090\u036b\3\2\2\2\u0092" + + "\u0376\3\2\2\2\u0094\u037f\3\2\2\2\u0096\u0388\3\2\2\2\u0098\u038d\3\2" + + "\2\2\u009a\u0393\3\2\2\2\u009c\u0395\3\2\2\2\u009e\u0399\3\2\2\2\u00a0" + + "\u03af\3\2\2\2\u00a2\u03b7\3\2\2\2\u00a4\u03bb\3\2\2\2\u00a6\u00a7\7-" + + "\2\2\u00a7\u00a8\3\2\2\2\u00a8\u00a9\b\2\2\2\u00a9\5\3\2\2\2\u00aa\u00ab" + + "\t\2\2\2\u00ab\u00ac\3\2\2\2\u00ac\u00ad\b\3\3\2\u00ad\7\3\2\2\2\u00ae" + + "\u00af\7\61\2\2\u00af\u00b0\7\61\2\2\u00b0\u00b4\3\2\2\2\u00b1\u00b3\n" + + "\3\2\2\u00b2\u00b1\3\2\2\2\u00b3\u00b6\3\2\2\2\u00b4\u00b2\3\2\2\2\u00b4" + + "\u00b5\3\2\2\2\u00b5\u00b7\3\2\2\2\u00b6\u00b4\3\2\2\2\u00b7\u00b8\b\4" + + "\4\2\u00b8\t\3\2\2\2\u00b9\u00ba\7\61\2\2\u00ba\u00bb\7,\2\2\u00bb\u00bf" + + "\3\2\2\2\u00bc\u00be\n\4\2\2\u00bd\u00bc\3\2\2\2\u00be\u00c1\3\2\2\2\u00bf" + + "\u00bd\3\2\2\2\u00bf\u00c0\3\2\2\2\u00c0\u00c2\3\2\2\2\u00c1\u00bf\3\2" + + "\2\2\u00c2\u00c3\7,\2\2\u00c3\u00c4\7\61\2\2\u00c4\u00c5\3\2\2\2\u00c5" + + "\u00c6\b\5\5\2\u00c6\13\3\2\2\2\u00c7\u00c8\7=\2\2\u00c8\u00c9\3\2\2\2" + + "\u00c9\u00ca\b\6\6\2\u00ca\r\3\2\2\2\u00cb\u00cc\7}\2\2\u00cc\u00cd\3" + + "\2\2\2\u00cd\u00ce\b\7\7\2\u00ce\17\3\2\2\2\u00cf\u00d0\7\177\2\2\u00d0" + + "\u00d1\3\2\2\2\u00d1\u00d2\b\b\b\2\u00d2\21\3\2\2\2\u00d3\u00d4\7{\2\2" + + "\u00d4\u00d5\7k\2\2\u00d5\u00d6\7p\2\2\u00d6\u00d7\7/\2\2\u00d7\u00d8" + + "\7g\2\2\u00d8\u00d9\7n\2\2\u00d9\u00da\7g\2\2\u00da\u00db\7o\2\2\u00db" + + "\u00dc\7g\2\2\u00dc\u00dd\7p\2\2\u00dd\u00de\7v\2\2\u00de\u00df\3\2\2" + + "\2\u00df\u00e0\b\t\t\2\u00e0\23\3\2\2\2\u00e1\u00e2\7{\2\2\u00e2\u00e3" + + "\7c\2\2\u00e3\u00e4\7p\2\2\u00e4\u00e5\7i\2\2\u00e5\u00e6\7/\2\2\u00e6" + + "\u00e7\7x\2\2\u00e7\u00e8\7g\2\2\u00e8\u00e9\7t\2\2\u00e9\u00ea\7u\2\2" + + "\u00ea\u00eb\7k\2\2\u00eb\u00ec\7q\2\2\u00ec\u00ed\7p\2\2\u00ed\u00ee" + + "\3\2\2\2\u00ee\u00ef\b\n\n\2\u00ef\25\3\2\2\2\u00f0\u00f1\7y\2\2\u00f1" + + "\u00f2\7j\2\2\u00f2\u00f3\7g\2\2\u00f3\u00f4\7p\2\2\u00f4\u00f5\3\2\2" + + "\2\u00f5\u00f6\b\13\13\2\u00f6\27\3\2\2\2\u00f7\u00f8\7x\2\2\u00f8\u00f9" + + "\7c\2\2\u00f9\u00fa\7n\2\2\u00fa\u00fb\7w\2\2\u00fb\u00fc\7g\2\2\u00fc" + + "\u00fd\3\2\2\2\u00fd\u00fe\b\f\f\2\u00fe\31\3\2\2\2\u00ff\u0100\7w\2\2" + + "\u0100\u0101\7u\2\2\u0101\u0102\7g\2\2\u0102\u0103\7u\2\2\u0103\u0104" + + "\3\2\2\2\u0104\u0105\b\r\r\2\u0105\33\3\2\2\2\u0106\u0107\7w\2\2\u0107" + + "\u0108\7p\2\2\u0108\u0109\7k\2\2\u0109\u010a\7v\2\2\u010a\u010b\7u\2\2" + + "\u010b\u010c\3\2\2\2\u010c\u010d\b\16\16\2\u010d\35\3\2\2\2\u010e\u010f" + + "\7w\2\2\u010f\u0110\7p\2\2\u0110\u0111\7k\2\2\u0111\u0112\7s\2\2\u0112" + + "\u0113\7w\2\2\u0113\u0114\7g\2\2\u0114\u0115\3\2\2\2\u0115\u0116\b\17" + + "\17\2\u0116\37\3\2\2\2\u0117\u0118\7v\2\2\u0118\u0119\7{\2\2\u0119\u011a" + + "\7r\2\2\u011a\u011b\7g\2\2\u011b\u011c\7f\2\2\u011c\u011d\7g\2\2\u011d" + + "\u011e\7h\2\2\u011e\u011f\3\2\2\2\u011f\u0120\b\20\20\2\u0120!\3\2\2\2" + + "\u0121\u0122\7v\2\2\u0122\u0123\7{\2\2\u0123\u0124\7r\2\2\u0124\u0125" + + "\7g\2\2\u0125\u0126\3\2\2\2\u0126\u0127\b\21\21\2\u0127#\3\2\2\2\u0128" + + "\u0129\7u\2\2\u0129\u012a\7w\2\2\u012a\u012b\7d\2\2\u012b\u012c\7o\2\2" + + "\u012c\u012d\7q\2\2\u012d\u012e\7f\2\2\u012e\u012f\7w\2\2\u012f\u0130" + + "\7n\2\2\u0130\u0131\7g\2\2\u0131\u0132\3\2\2\2\u0132\u0133\b\22\22\2\u0133" + + "%\3\2\2\2\u0134\u0135\7u\2\2\u0135\u0136\7v\2\2\u0136\u0137\7c\2\2\u0137" + + "\u0138\7v\2\2\u0138\u0139\7w\2\2\u0139\u013a\7u\2\2\u013a\u013b\3\2\2" + + "\2\u013b\u013c\b\23\23\2\u013c\'\3\2\2\2\u013d\u013e\7t\2\2\u013e\u013f" + + "\7r\2\2\u013f\u0140\7e\2\2\u0140\u0141\3\2\2\2\u0141\u0142\b\24\24\2\u0142" + + ")\3\2\2\2\u0143\u0144\7t\2\2\u0144\u0145\7g\2\2\u0145\u0146\7x\2\2\u0146" + + "\u0147\7k\2\2\u0147\u0148\7u\2\2\u0148\u0149\7k\2\2\u0149\u014a\7q\2\2" + + "\u014a\u014b\7p\2\2\u014b\u014c\7/\2\2\u014c\u014d\7f\2\2\u014d\u014e" + + "\7c\2\2\u014e\u014f\7v\2\2\u014f\u0150\7g\2\2\u0150\u0151\3\2\2\2\u0151" + + "\u0152\b\25\25\2\u0152+\3\2\2\2\u0153\u0154\7t\2\2\u0154\u0155\7g\2\2" + + "\u0155\u0156\7x\2\2\u0156\u0157\7k\2\2\u0157\u0158\7u\2\2\u0158\u0159" + + "\7k\2\2\u0159\u015a\7q\2\2\u015a\u015b\7p\2\2\u015b\u015c\3\2\2\2\u015c" + + "\u015d\b\26\26\2\u015d-\3\2\2\2\u015e\u015f\7t\2\2\u015f\u0160\7g\2\2" + + "\u0160\u0161\7s\2\2\u0161\u0162\7w\2\2\u0162\u0163\7k\2\2\u0163\u0164" + + "\7t\2\2\u0164\u0165\7g\2\2\u0165\u0166\7/\2\2\u0166\u0167\7k\2\2\u0167" + + "\u0168\7p\2\2\u0168\u0169\7u\2\2\u0169\u016a\7v\2\2\u016a\u016b\7c\2\2" + + "\u016b\u016c\7p\2\2\u016c\u016d\7e\2\2\u016d\u016e\7g\2\2\u016e\u016f" + + "\3\2\2\2\u016f\u0170\b\27\27\2\u0170/\3\2\2\2\u0171\u0172\7t\2\2\u0172" + + "\u0173\7g\2\2\u0173\u0174\7h\2\2\u0174\u0175\7k\2\2\u0175\u0176\7p\2\2" + + "\u0176\u0177\7g\2\2\u0177\u0178\3\2\2\2\u0178\u0179\b\30\30\2\u0179\61" + + "\3\2\2\2\u017a\u017b\7t\2\2\u017b\u017c\7g\2\2\u017c\u017d\7h\2\2\u017d" + + "\u017e\7g\2\2\u017e\u017f\7t\2\2\u017f\u0180\7g\2\2\u0180\u0181\7p\2\2" + + "\u0181\u0182\7e\2\2\u0182\u0183\7g\2\2\u0183\u0184\3\2\2\2\u0184\u0185" + + "\b\31\31\2\u0185\63\3\2\2\2\u0186\u0187\7t\2\2\u0187\u0188\7c\2\2\u0188" + + "\u0189\7p\2\2\u0189\u018a\7i\2\2\u018a\u018b\7g\2\2\u018b\u018c\3\2\2" + + "\2\u018c\u018d\b\32\32\2\u018d\65\3\2\2\2\u018e\u018f\7r\2\2\u018f\u0190" + + "\7t\2\2\u0190\u0191\7g\2\2\u0191\u0192\7u\2\2\u0192\u0193\7g\2\2\u0193" + + "\u0194\7p\2\2\u0194\u0195\7e\2\2\u0195\u0196\7g\2\2\u0196\u0197\3\2\2" + + "\2\u0197\u0198\b\33\33\2\u0198\67\3\2\2\2\u0199\u019a\7r\2\2\u019a\u019b" + + "\7t\2\2\u019b\u019c\7g\2\2\u019c\u019d\7h\2\2\u019d\u019e\7k\2\2\u019e" + + "\u019f\7z\2\2\u019f\u01a0\3\2\2\2\u01a0\u01a1\b\34\34\2\u01a19\3\2\2\2" + + "\u01a2\u01a3\7r\2\2\u01a3\u01a4\7q\2\2\u01a4\u01a5\7u\2\2\u01a5\u01a6" + + "\7k\2\2\u01a6\u01a7\7v\2\2\u01a7\u01a8\7k\2\2\u01a8\u01a9\7q\2\2\u01a9" + + "\u01aa\7p\2\2\u01aa\u01ab\3\2\2\2\u01ab\u01ac\b\35\35\2\u01ac;\3\2\2\2" + + "\u01ad\u01ae\7r\2\2\u01ae\u01af\7c\2\2\u01af\u01b0\7v\2\2\u01b0\u01b1" + + "\7v\2\2\u01b1\u01b2\7g\2\2\u01b2\u01b3\7t\2\2\u01b3\u01b4\7p\2\2\u01b4" + + "\u01b5\3\2\2\2\u01b5\u01b6\b\36\36\2\u01b6=\3\2\2\2\u01b7\u01b8\7r\2\2" + + "\u01b8\u01b9\7c\2\2\u01b9\u01ba\7v\2\2\u01ba\u01bb\7j\2\2\u01bb\u01bc" + + "\3\2\2\2\u01bc\u01bd\b\37\37\2\u01bd?\3\2\2\2\u01be\u01bf\7q\2\2\u01bf" + + "\u01c0\7w\2\2\u01c0\u01c1\7v\2\2\u01c1\u01c2\7r\2\2\u01c2\u01c3\7w\2\2" + + "\u01c3\u01c4\7v\2\2\u01c4A\3\2\2\2\u01c5\u01c6\7q\2\2\u01c6\u01c7\7t\2" + + "\2\u01c7\u01c8\7i\2\2\u01c8\u01c9\7c\2\2\u01c9\u01ca\7p\2\2\u01ca\u01cb" + + "\7k\2\2\u01cb\u01cc\7|\2\2\u01cc\u01cd\7c\2\2\u01cd\u01ce\7v\2\2\u01ce" + + "\u01cf\7k\2\2\u01cf\u01d0\7q\2\2\u01d0\u01d1\7p\2\2\u01d1\u01d2\3\2\2" + + "\2\u01d2\u01d3\b! \2\u01d3C\3\2\2\2\u01d4\u01d5\7q\2\2\u01d5\u01d6\7t" + + "\2\2\u01d6\u01d7\7f\2\2\u01d7\u01d8\7g\2\2\u01d8\u01d9\7t\2\2\u01d9\u01da" + + "\7g\2\2\u01da\u01db\7f\2\2\u01db\u01dc\7/\2\2\u01dc\u01dd\7d\2\2\u01dd" + + "\u01de\7{\2\2\u01de\u01df\3\2\2\2\u01df\u01e0\b\"!\2\u01e0E\3\2\2\2\u01e1" + + "\u01e2\7p\2\2\u01e2\u01e3\7q\2\2\u01e3\u01e4\7v\2\2\u01e4\u01e5\7k\2\2" + + "\u01e5\u01e6\7h\2\2\u01e6\u01e7\7k\2\2\u01e7\u01e8\7e\2\2\u01e8\u01e9" + + "\7c\2\2\u01e9\u01ea\7v\2\2\u01ea\u01eb\7k\2\2\u01eb\u01ec\7q\2\2\u01ec" + + "\u01ed\7p\2\2\u01ed\u01ee\3\2\2\2\u01ee\u01ef\b#\"\2\u01efG\3\2\2\2\u01f0" + + "\u01f1\7p\2\2\u01f1\u01f2\7c\2\2\u01f2\u01f3\7o\2\2\u01f3\u01f4\7g\2\2" + + "\u01f4\u01f5\7u\2\2\u01f5\u01f6\7r\2\2\u01f6\u01f7\7c\2\2\u01f7\u01f8" + + "\7e\2\2\u01f8\u01f9\7g\2\2\u01f9\u01fa\3\2\2\2\u01fa\u01fb\b$#\2\u01fb" + + "I\3\2\2\2\u01fc\u01fd\7o\2\2\u01fd\u01fe\7w\2\2\u01fe\u01ff\7u\2\2\u01ff" + + "\u0200\7v\2\2\u0200\u0201\3\2\2\2\u0201\u0202\b%$\2\u0202K\3\2\2\2\u0203" + + "\u0204\7o\2\2\u0204\u0205\7q\2\2\u0205\u0206\7f\2\2\u0206\u0207\7w\2\2" + + "\u0207\u0208\7n\2\2\u0208\u0209\7g\2\2\u0209\u020a\3\2\2\2\u020a\u020b" + + "\b&%\2\u020bM\3\2\2\2\u020c\u020d\7o\2\2\u020d\u020e\7k\2\2\u020e\u020f" + + "\7p\2\2\u020f\u0210\7/\2\2\u0210\u0211\7g\2\2\u0211\u0212\7n\2\2\u0212" + + "\u0213\7g\2\2\u0213\u0214\7o\2\2\u0214\u0215\7g\2\2\u0215\u0216\7p\2\2" + + "\u0216\u0217\7v\2\2\u0217\u0218\7u\2\2\u0218\u0219\3\2\2\2\u0219\u021a" + + "\b\'&\2\u021aO\3\2\2\2\u021b\u021c\7o\2\2\u021c\u021d\7c\2\2\u021d\u021e" + + "\7z\2\2\u021e\u021f\7/\2\2\u021f\u0220\7g\2\2\u0220\u0221\7n\2\2\u0221" + + "\u0222\7g\2\2\u0222\u0223\7o\2\2\u0223\u0224\7g\2\2\u0224\u0225\7p\2\2" + + "\u0225\u0226\7v\2\2\u0226\u0227\7u\2\2\u0227\u0228\3\2\2\2\u0228\u0229" + + "\b(\'\2\u0229Q\3\2\2\2\u022a\u022b\7o\2\2\u022b\u022c\7c\2\2\u022c\u022d" + + "\7p\2\2\u022d\u022e\7f\2\2\u022e\u022f\7c\2\2\u022f\u0230\7v\2\2\u0230" + + "\u0231\7q\2\2\u0231\u0232\7t\2\2\u0232\u0233\7{\2\2\u0233\u0234\3\2\2" + + "\2\u0234\u0235\b)(\2\u0235S\3\2\2\2\u0236\u0237\7n\2\2\u0237\u0238\7k" + + "\2\2\u0238\u0239\7u\2\2\u0239\u023a\7v\2\2\u023a\u023b\3\2\2\2\u023b\u023c" + + "\b*)\2\u023cU\3\2\2\2\u023d\u023e\7n\2\2\u023e\u023f\7g\2\2\u023f\u0240" + + "\7p\2\2\u0240\u0241\7i\2\2\u0241\u0242\7v\2\2\u0242\u0243\7j\2\2\u0243" + + "\u0244\3\2\2\2\u0244\u0245\b+*\2\u0245W\3\2\2\2\u0246\u0247\7n\2\2\u0247" + + "\u0248\7g\2\2\u0248\u0249\7c\2\2\u0249\u024a\7h\2\2\u024a\u024b\7/\2\2" + + "\u024b\u024c\7n\2\2\u024c\u024d\7k\2\2\u024d\u024e\7u\2\2\u024e\u024f" + + "\7v\2\2\u024f\u0250\3\2\2\2\u0250\u0251\b,+\2\u0251Y\3\2\2\2\u0252\u0253" + + "\7n\2\2\u0253\u0254\7g\2\2\u0254\u0255\7c\2\2\u0255\u0256\7h\2\2\u0256" + + "\u0257\3\2\2\2\u0257\u0258\b-,\2\u0258[\3\2\2\2\u0259\u025a\7m\2\2\u025a" + + "\u025b\7g\2\2\u025b\u025c\7{\2\2\u025c\u025d\3\2\2\2\u025d\u025e\b.-\2" + + "\u025e]\3\2\2\2\u025f\u0260\7k\2\2\u0260\u0261\7p\2\2\u0261\u0262\7r\2" + + "\2\u0262\u0263\7w\2\2\u0263\u0264\7v\2\2\u0264_\3\2\2\2\u0265\u0266\7" + + "k\2\2\u0266\u0267\7p\2\2\u0267\u0268\7e\2\2\u0268\u0269\7n\2\2\u0269\u026a" + + "\7w\2\2\u026a\u026b\7f\2\2\u026b\u026c\7g\2\2\u026c\u026d\3\2\2\2\u026d" + + "\u026e\b\60.\2\u026ea\3\2\2\2\u026f\u0270\7k\2\2\u0270\u0271\7o\2\2\u0271" + + "\u0272\7r\2\2\u0272\u0273\7q\2\2\u0273\u0274\7t\2\2\u0274\u0275\7v\2\2" + + "\u0275\u0276\3\2\2\2\u0276\u0277\b\61/\2\u0277c\3\2\2\2\u0278\u0279\7" + + "k\2\2\u0279\u027a\7h\2\2\u027a\u027b\7/\2\2\u027b\u027c\7h\2\2\u027c\u027d" + + "\7g\2\2\u027d\u027e\7c\2\2\u027e\u027f\7v\2\2\u027f\u0280\7w\2\2\u0280" + + "\u0281\7t\2\2\u0281\u0282\7g\2\2\u0282\u0283\3\2\2\2\u0283\u0284\b\62" + + "\60\2\u0284e\3\2\2\2\u0285\u0286\7k\2\2\u0286\u0287\7f\2\2\u0287\u0288" + + "\7g\2\2\u0288\u0289\7p\2\2\u0289\u028a\7v\2\2\u028a\u028b\7k\2\2\u028b" + + "\u028c\7v\2\2\u028c\u028d\7{\2\2\u028d\u028e\3\2\2\2\u028e\u028f\b\63" + + "\61\2\u028fg\3\2\2\2\u0290\u0291\7i\2\2\u0291\u0292\7t\2\2\u0292\u0293" + + "\7q\2\2\u0293\u0294\7w\2\2\u0294\u0295\7r\2\2\u0295\u0296\7k\2\2\u0296" + + "\u0297\7p\2\2\u0297\u0298\7i\2\2\u0298\u0299\3\2\2\2\u0299\u029a\b\64" + + "\62\2\u029ai\3\2\2\2\u029b\u029c\7h\2\2\u029c\u029d\7t\2\2\u029d\u029e" + + "\7c\2\2\u029e\u029f\7e\2\2\u029f\u02a0\7v\2\2\u02a0\u02a1\7k\2\2\u02a1" + + "\u02a2\7q\2\2\u02a2\u02a3\7p\2\2\u02a3\u02a4\7/\2\2\u02a4\u02a5\7f\2\2" + + "\u02a5\u02a6\7k\2\2\u02a6\u02a7\7i\2\2\u02a7\u02a8\7k\2\2\u02a8\u02a9" + + "\7v\2\2\u02a9\u02aa\7u\2\2\u02aa\u02ab\3\2\2\2\u02ab\u02ac\b\65\63\2\u02ac" + + "k\3\2\2\2\u02ad\u02ae\7h\2\2\u02ae\u02af\7g\2\2\u02af\u02b0\7c\2\2\u02b0" + + "\u02b1\7v\2\2\u02b1\u02b2\7w\2\2\u02b2\u02b3\7t\2\2\u02b3\u02b4\7g\2\2" + + "\u02b4\u02b5\3\2\2\2\u02b5\u02b6\b\66\64\2\u02b6m\3\2\2\2\u02b7\u02b8" + + "\7f\2\2\u02b8\u02b9\7g\2\2\u02b9\u02ba\7x\2\2\u02ba\u02bb\7k\2\2\u02bb" + + "\u02bc\7c\2\2\u02bc\u02bd\7v\2\2\u02bd\u02be\7g\2\2\u02be\u02bf\3\2\2" + + "\2\u02bf\u02c0\b\67\65\2\u02c0o\3\2\2\2\u02c1\u02c2\7f\2\2\u02c2\u02c3" + + "\7g\2\2\u02c3\u02c4\7x\2\2\u02c4\u02c5\7k\2\2\u02c5\u02c6\7c\2\2\u02c6" + + "\u02c7\7v\2\2\u02c7\u02c8\7k\2\2\u02c8\u02c9\7q\2\2\u02c9\u02ca\7p\2\2" + + "\u02ca\u02cb\3\2\2\2\u02cb\u02cc\b8\66\2\u02ccq\3\2\2\2\u02cd\u02ce\7" + + "g\2\2\u02ce\u02cf\7z\2\2\u02cf\u02d0\7v\2\2\u02d0\u02d1\7g\2\2\u02d1\u02d2" + + "\7p\2\2\u02d2\u02d3\7u\2\2\u02d3\u02d4\7k\2\2\u02d4\u02d5\7q\2\2\u02d5" + + "\u02d6\7p\2\2\u02d6\u02d7\3\2\2\2\u02d7\u02d8\b9\67\2\u02d8s\3\2\2\2\u02d9" + + "\u02da\7g\2\2\u02da\u02db\7t\2\2\u02db\u02dc\7t\2\2\u02dc\u02dd\7q\2\2" + + "\u02dd\u02de\7t\2\2\u02de\u02df\7/\2\2\u02df\u02e0\7o\2\2\u02e0\u02e1" + + "\7g\2\2\u02e1\u02e2\7u\2\2\u02e2\u02e3\7u\2\2\u02e3\u02e4\7c\2\2\u02e4" + + "\u02e5\7i\2\2\u02e5\u02e6\7g\2\2\u02e6\u02e7\3\2\2\2\u02e7\u02e8\b:8\2" + + "\u02e8u\3\2\2\2\u02e9\u02ea\7g\2\2\u02ea\u02eb\7t\2\2\u02eb\u02ec\7t\2" + + "\2\u02ec\u02ed\7q\2\2\u02ed\u02ee\7t\2\2\u02ee\u02ef\7/\2\2\u02ef\u02f0" + + "\7c\2\2\u02f0\u02f1\7r\2\2\u02f1\u02f2\7r\2\2\u02f2\u02f3\7/\2\2\u02f3" + + "\u02f4\7v\2\2\u02f4\u02f5\7c\2\2\u02f5\u02f6\7i\2\2\u02f6\u02f7\3\2\2" + + "\2\u02f7\u02f8\b;9\2\u02f8w\3\2\2\2\u02f9\u02fa\7g\2\2\u02fa\u02fb\7p" + + "\2\2\u02fb\u02fc\7w\2\2\u02fc\u02fd\7o\2\2\u02fd\u02fe\3\2\2\2\u02fe\u02ff" + + "\b<:\2\u02ffy\3\2\2\2\u0300\u0301\7f\2\2\u0301\u0302\7g\2\2\u0302\u0303" + + "\7u\2\2\u0303\u0304\7e\2\2\u0304\u0305\7t\2\2\u0305\u0306\7k\2\2\u0306" + + "\u0307\7r\2\2\u0307\u0308\7v\2\2\u0308\u0309\7k\2\2\u0309\u030a\7q\2\2" + + "\u030a\u030b\7p\2\2\u030b\u030c\3\2\2\2\u030c\u030d\b=;\2\u030d{\3\2\2" + + "\2\u030e\u030f\7f\2\2\u030f\u0310\7g\2\2\u0310\u0311\7h\2\2\u0311\u0312" + + "\7c\2\2\u0312\u0313\7w\2\2\u0313\u0314\7n\2\2\u0314\u0315\7v\2\2\u0315" + + "\u0316\3\2\2\2\u0316\u0317\b><\2\u0317}\3\2\2\2\u0318\u0319\7e\2\2\u0319" + + "\u031a\7q\2\2\u031a\u031b\7p\2\2\u031b\u031c\7v\2\2\u031c\u031d\7c\2\2" + + "\u031d\u031e\7k\2\2\u031e\u031f\7p\2\2\u031f\u0320\7g\2\2\u0320\u0321" + + "\7t\2\2\u0321\u0322\3\2\2\2\u0322\u0323\b?=\2\u0323\177\3\2\2\2\u0324" + + "\u0325\7e\2\2\u0325\u0326\7q\2\2\u0326\u0327\7p\2\2\u0327\u0328\7v\2\2" + + "\u0328\u0329\7c\2\2\u0329\u032a\7e\2\2\u032a\u032b\7v\2\2\u032b\u032c" + + "\3\2\2\2\u032c\u032d\b@>\2\u032d\u0081\3\2\2\2\u032e\u032f\7e\2\2\u032f" + + "\u0330\7q\2\2\u0330\u0331\7p\2\2\u0331\u0332\7h\2\2\u0332\u0333\7k\2\2" + + "\u0333\u0334\7i\2\2\u0334\u0335\3\2\2\2\u0335\u0336\bA?\2\u0336\u0083" + + "\3\2\2\2\u0337\u0338\7e\2\2\u0338\u0339\7j\2\2\u0339\u033a\7q\2\2\u033a" + + "\u033b\7k\2\2\u033b\u033c\7e\2\2\u033c\u033d\7g\2\2\u033d\u033e\3\2\2" + + "\2\u033e\u033f\bB@\2\u033f\u0085\3\2\2\2\u0340\u0341\7e\2\2\u0341\u0342" + + "\7c\2\2\u0342\u0343\7u\2\2\u0343\u0344\7g\2\2\u0344\u0345\3\2\2\2\u0345" + + "\u0346\bCA\2\u0346\u0087\3\2\2\2\u0347\u0348\7d\2\2\u0348\u0349\7k\2\2" + + "\u0349\u034a\7v\2\2\u034a\u034b\3\2\2\2\u034b\u034c\bDB\2\u034c\u0089" + + "\3\2\2\2\u034d\u034e\7d\2\2\u034e\u034f\7g\2\2\u034f\u0350\7n\2\2\u0350" + + "\u0351\7q\2\2\u0351\u0352\7p\2\2\u0352\u0353\7i\2\2\u0353\u0354\7u\2\2" + + "\u0354\u0355\7/\2\2\u0355\u0356\7v\2\2\u0356\u0357\7q\2\2\u0357\u0358" + + "\3\2\2\2\u0358\u0359\bEC\2\u0359\u008b\3\2\2\2\u035a\u035b\7d\2\2\u035b" + + "\u035c\7c\2\2\u035c\u035d\7u\2\2\u035d\u035e\7g\2\2\u035e\u035f\3\2\2" + + "\2\u035f\u0360\bFD\2\u0360\u008d\3\2\2\2\u0361\u0362\7c\2\2\u0362\u0363" + + "\7w\2\2\u0363\u0364\7i\2\2\u0364\u0365\7o\2\2\u0365\u0366\7g\2\2\u0366" + + "\u0367\7p\2\2\u0367\u0368\7v\2\2\u0368\u0369\3\2\2\2\u0369\u036a\bGE\2" + + "\u036a\u008f\3\2\2\2\u036b\u036c\7c\2\2\u036c\u036d\7t\2\2\u036d\u036e" + + "\7i\2\2\u036e\u036f\7w\2\2\u036f\u0370\7o\2\2\u0370\u0371\7g\2\2\u0371" + + "\u0372\7p\2\2\u0372\u0373\7v\2\2\u0373\u0374\3\2\2\2\u0374\u0375\bHF\2" + + "\u0375\u0091\3\2\2\2\u0376\u0377\7c\2\2\u0377\u0378\7p\2\2\u0378\u0379" + + "\7{\2\2\u0379\u037a\7z\2\2\u037a\u037b\7o\2\2\u037b\u037c\7n\2\2\u037c" + + "\u037d\3\2\2\2\u037d\u037e\bIG\2\u037e\u0093\3\2\2\2\u037f\u0383\t\5\2" + + "\2\u0380\u0382\t\6\2\2\u0381\u0380\3\2\2\2\u0382\u0385\3\2\2\2\u0383\u0381" + + "\3\2\2\2\u0383\u0384\3\2\2\2\u0384\u0386\3\2\2\2\u0385\u0383\3\2\2\2\u0386" + + "\u0387\bJH\2\u0387\u0095\3\2\2\2\u0388\u038b\7^\2\2\u0389\u038c\t\7\2" + + "\2\u038a\u038c\5\u0098L\2\u038b\u0389\3\2\2\2\u038b\u038a\3\2\2\2\u038c" + + "\u0097\3\2\2\2\u038d\u038e\7w\2\2\u038e\u038f\5\u009aM\2\u038f\u0390\5" + + "\u009aM\2\u0390\u0391\5\u009aM\2\u0391\u0392\5\u009aM\2\u0392\u0099\3" + + "\2\2\2\u0393\u0394\t\b\2\2\u0394\u009b\3\2\2\2\u0395\u0396\7=\2\2\u0396" + + "\u0397\3\2\2\2\u0397\u0398\bNI\2\u0398\u009d\3\2\2\2\u0399\u039a\7}\2" + + "\2\u039a\u039b\3\2\2\2\u039b\u039c\bOJ\2\u039c\u009f\3\2\2\2\u039d\u03a2" + + "\7$\2\2\u039e\u03a1\5\u0096K\2\u039f\u03a1\n\t\2\2\u03a0\u039e\3\2\2\2" + + "\u03a0\u039f\3\2\2\2\u03a1\u03a4\3\2\2\2\u03a2\u03a0\3\2\2\2\u03a2\u03a3" + + "\3\2\2\2\u03a3\u03a5\3\2\2\2\u03a4\u03a2\3\2\2\2\u03a5\u03b0\7$\2\2\u03a6" + + "\u03ab\7)\2\2\u03a7\u03aa\5\u0096K\2\u03a8\u03aa\n\n\2\2\u03a9\u03a7\3" + + "\2\2\2\u03a9\u03a8\3\2\2\2\u03aa\u03ad\3\2\2\2\u03ab\u03a9\3\2\2\2\u03ab" + + "\u03ac\3\2\2\2\u03ac\u03ae\3\2\2\2\u03ad\u03ab\3\2\2\2\u03ae\u03b0\7)" + + "\2\2\u03af\u039d\3\2\2\2\u03af\u03a6\3\2\2\2\u03b0\u00a1\3\2\2\2\u03b1" + + "\u03b8\5\u00a0P\2\u03b2\u03b4\n\13\2\2\u03b3\u03b2\3\2\2\2\u03b4\u03b5" + + "\3\2\2\2\u03b5\u03b3\3\2\2\2\u03b5\u03b6\3\2\2\2\u03b6\u03b8\3\2\2\2\u03b7" + + "\u03b1\3\2\2\2\u03b7\u03b3\3\2\2\2\u03b8\u03b9\3\2\2\2\u03b9\u03ba\bQ" + + "K\2\u03ba\u00a3\3\2\2\2\u03bb\u03bc\t\f\2\2\u03bc\u03bd\3\2\2\2\u03bd" + + "\u03be\bRL\2\u03be\u00a5\3\2\2\2\17\2\3\u00b4\u00bf\u0383\u038b\u03a0" + + "\u03a2\u03a9\u03ab\u03af\u03b5\u03b7"; + public static final ATN _ATN = ATNSimulator.deserialize(_serializedATN + .toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParser.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParser.java new file mode 100644 index 0000000000..2b22fc7396 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParser.java @@ -0,0 +1,13367 @@ +/* + * 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.controller.antlrv4.code.gen; + +import java.util.List; + +import org.antlr.v4.runtime.NoViableAltException; +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNSimulator; +import org.antlr.v4.runtime.atn.ParserATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.tree.ParseTreeListener; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; +import org.antlr.v4.runtime.tree.TerminalNode; + +@SuppressWarnings({ "all", "warnings", "unchecked", "unused", "cast" }) +public class YangParser extends Parser { + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); + public static final int CHOICE_KEYWORD = 65, YIN_ELEMENT_KEYWORD = 8, + WHEN_KEYWORD = 10, REVISION_KEYWORD = 21, DESCRIPTION_KEYWORD = 60, + NAMESPACE_KEYWORD = 35, MODULE_KEYWORD = 37, + REFERENCE_KEYWORD = 24, CONTACT_KEYWORD = 63, + LEAF_LIST_KEYWORD = 43, REVISION_DATE_KEYWORD = 20, + BELONGS_TO_KEYWORD = 68, LEAF_KEYWORD = 44, PREFIX_KEYWORD = 27, + DEFAULT_KEYWORD = 61, PRESENCE_KEYWORD = 26, ARGUMENT_KEYWORD = 71, + NOTIFICATION_KEYWORD = 34, RPC_KEYWORD = 19, + CONTAINER_KEYWORD = 62, DEVIATION_KEYWORD = 55, + STATUS_KEYWORD = 18, IDENTITY_KEYWORD = 50, IDENTIFIER = 73, + REFINE_KEYWORD = 23, USES_KEYWORD = 12, VALUE_KEYWORD = 11, + IMPORT_KEYWORD = 48, BLOCK_COMMENT = 7, INPUT_KEYWORD = 46, + IF_FEATURE_KEYWORD = 49, PLUS = 4, PATTERN_KEYWORD = 29, + LENGTH_KEYWORD = 42, FEATURE_KEYWORD = 53, + REQUIRE_INSTANCE_KEYWORD = 22, ORGANIZATION_KEYWORD = 32, + UNIQUE_KEYWORD = 14, SUBMODULE_KEYWORD = 17, TYPE_KEYWORD = 16, + RIGHT_BRACE = 3, ERROR_MESSAGE_KEYWORD = 57, LINE_COMMENT = 6, + OUTPUT_KEYWORD = 31, MIN_ELEMENTS_KEYWORD = 38, MUST_KEYWORD = 36, + SEMICOLON = 1, POSITION_KEYWORD = 28, PATH_KEYWORD = 30, S = 75, + KEY_KEYWORD = 45, EXTENSION_KEYWORD = 56, WS = 5, + MANDATORY_KEYWORD = 40, ORDERED_BY_KEYWORD = 33, + ERROR_APP_TAG_KEYWORD = 58, INCLUDE_KEYWORD = 47, + ANYXML_KEYWORD = 72, AUGMENT_KEYWORD = 70, DEVIATE_KEYWORD = 54, + LEFT_BRACE = 2, YANG_VERSION_KEYWORD = 9, LIST_KEYWORD = 41, + TYPEDEF_KEYWORD = 15, MAX_ELEMENTS_KEYWORD = 39, ENUM_KEYWORD = 59, + CASE_KEYWORD = 66, UNITS_KEYWORD = 13, GROUPING_KEYWORD = 51, + BASE_KEYWORD = 69, RANGE_KEYWORD = 25, + FRACTION_DIGITS_KEYWORD = 52, CONFIG_KEYWORD = 64, + BIT_KEYWORD = 67, STRING = 74; + public static final String[] tokenNames = { "", "SEMICOLON", + "LEFT_BRACE", "'}'", "'+'", "WS", "LINE_COMMENT", "BLOCK_COMMENT", + "'yin-element'", "'yang-version'", "'when'", "'value'", "'uses'", + "'units'", "'unique'", "'typedef'", "'type'", "'submodule'", + "'status'", "'rpc'", "'revision-date'", "'revision'", + "'require-instance'", "'refine'", "'reference'", "'range'", + "'presence'", "'prefix'", "'position'", "'pattern'", "'path'", + "'output'", "'organization'", "'ordered-by'", "'notification'", + "'namespace'", "'must'", "'module'", "'min-elements'", + "'max-elements'", "'mandatory'", "'list'", "'length'", + "'leaf-list'", "'leaf'", "'key'", "'input'", "'include'", + "'import'", "'if-feature'", "'identity'", "'grouping'", + "'fraction-digits'", "'feature'", "'deviate'", "'deviation'", + "'extension'", "'error-message'", "'error-app-tag'", "'enum'", + "'description'", "'default'", "'container'", "'contact'", + "'config'", "'choice'", "'case'", "'bit'", "'belongs-to'", + "'base'", "'augment'", "'argument'", "'anyxml'", "IDENTIFIER", + "STRING", "S" }; + public static final int RULE_yang = 0, RULE_string = 1, + RULE_identifier_stmt = 2, RULE_stmtend = 3, + RULE_deviate_replace_stmt = 4, RULE_deviate_delete_stmt = 5, + RULE_deviate_add_stmt = 6, RULE_deviate_not_supported_stmt = 7, + RULE_deviation_stmt = 8, RULE_notification_stmt = 9, + RULE_output_stmt = 10, RULE_input_stmt = 11, RULE_rpc_stmt = 12, + RULE_when_stmt = 13, RULE_augment_stmt = 14, + RULE_uses_augment_stmt = 15, RULE_refine_anyxml_stmts = 16, + RULE_refine_case_stmts = 17, RULE_refine_choice_stmts = 18, + RULE_refine_list_stmts = 19, RULE_refine_leaf_list_stmts = 20, + RULE_refine_leaf_stmts = 21, RULE_refine_container_stmts = 22, + RULE_refune_pom = 23, RULE_refine_stmt = 24, RULE_uses_stmt = 25, + RULE_anyxml_stmt = 26, RULE_case_stmt = 27, + RULE_short_case_stmt = 28, RULE_choice_stmt = 29, + RULE_unique_stmt = 30, RULE_key_stmt = 31, RULE_list_stmt = 32, + RULE_leaf_list_stmt = 33, RULE_leaf_stmt = 34, + RULE_container_stmt = 35, RULE_grouping_stmt = 36, + RULE_value_stmt = 37, RULE_max_value_arg = 38, + RULE_max_elements_stmt = 39, RULE_min_elements_stmt = 40, + RULE_error_app_tag_stmt = 41, RULE_error_message_stmt = 42, + RULE_must_stmt = 43, RULE_ordered_by_arg = 44, + RULE_ordered_by_stmt = 45, RULE_presence_stmt = 46, + RULE_mandatory_arg = 47, RULE_mandatory_stmt = 48, + RULE_config_arg = 49, RULE_config_stmt = 50, RULE_status_arg = 51, + RULE_status_stmt = 52, RULE_position_stmt = 53, RULE_bit_stmt = 54, + RULE_bits_specification = 55, RULE_union_specification = 56, + RULE_identityref_specification = 57, + RULE_instance_identifier_specification = 58, + RULE_require_instance_arg = 59, RULE_require_instance_stmt = 60, + RULE_path_stmt = 61, RULE_leafref_specification = 62, + RULE_enum_stmt = 63, RULE_enum_specification = 64, + RULE_default_stmt = 65, RULE_pattern_stmt = 66, + RULE_length_stmt = 67, RULE_string_restrictions = 68, + RULE_fraction_digits_stmt = 69, RULE_decimal64_specification = 70, + RULE_range_stmt = 71, RULE_numerical_restrictions = 72, + RULE_type_body_stmts = 73, RULE_type_stmt = 74, + RULE_typedef_stmt = 75, RULE_if_feature_stmt = 76, + RULE_feature_stmt = 77, RULE_base_stmt = 78, + RULE_identity_stmt = 79, RULE_yin_element_arg = 80, + RULE_yin_element_stmt = 81, RULE_argument_stmt = 82, + RULE_extension_stmt = 83, RULE_revision_date_stmt = 84, + RULE_revision_stmt = 85, RULE_units_stmt = 86, + RULE_reference_stmt = 87, RULE_description_stmt = 88, + RULE_contact_stmt = 89, RULE_organization_stmt = 90, + RULE_belongs_to_stmt = 91, RULE_prefix_stmt = 92, + RULE_namespace_stmt = 93, RULE_include_stmt = 94, + RULE_import_stmt = 95, RULE_yang_version_stmt = 96, + RULE_data_def_stmt = 97, RULE_body_stmts = 98, + RULE_revision_stmts = 99, RULE_linkage_stmts = 100, + RULE_meta_stmts = 101, RULE_submodule_header_stmts = 102, + RULE_module_header_stmts = 103, RULE_submodule_stmt = 104, + RULE_module_stmt = 105; + public static final String[] ruleNames = { "yang", "string", + "identifier_stmt", "stmtend", "deviate_replace_stmt", + "deviate_delete_stmt", "deviate_add_stmt", + "deviate_not_supported_stmt", "deviation_stmt", + "notification_stmt", "output_stmt", "input_stmt", "rpc_stmt", + "when_stmt", "augment_stmt", "uses_augment_stmt", + "refine_anyxml_stmts", "refine_case_stmts", "refine_choice_stmts", + "refine_list_stmts", "refine_leaf_list_stmts", "refine_leaf_stmts", + "refine_container_stmts", "refune_pom", "refine_stmt", "uses_stmt", + "anyxml_stmt", "case_stmt", "short_case_stmt", "choice_stmt", + "unique_stmt", "key_stmt", "list_stmt", "leaf_list_stmt", + "leaf_stmt", "container_stmt", "grouping_stmt", "value_stmt", + "max_value_arg", "max_elements_stmt", "min_elements_stmt", + "error_app_tag_stmt", "error_message_stmt", "must_stmt", + "ordered_by_arg", "ordered_by_stmt", "presence_stmt", + "mandatory_arg", "mandatory_stmt", "config_arg", "config_stmt", + "status_arg", "status_stmt", "position_stmt", "bit_stmt", + "bits_specification", "union_specification", + "identityref_specification", "instance_identifier_specification", + "require_instance_arg", "require_instance_stmt", "path_stmt", + "leafref_specification", "enum_stmt", "enum_specification", + "default_stmt", "pattern_stmt", "length_stmt", + "string_restrictions", "fraction_digits_stmt", + "decimal64_specification", "range_stmt", "numerical_restrictions", + "type_body_stmts", "type_stmt", "typedef_stmt", "if_feature_stmt", + "feature_stmt", "base_stmt", "identity_stmt", "yin_element_arg", + "yin_element_stmt", "argument_stmt", "extension_stmt", + "revision_date_stmt", "revision_stmt", "units_stmt", + "reference_stmt", "description_stmt", "contact_stmt", + "organization_stmt", "belongs_to_stmt", "prefix_stmt", + "namespace_stmt", "include_stmt", "import_stmt", + "yang_version_stmt", "data_def_stmt", "body_stmts", + "revision_stmts", "linkage_stmts", "meta_stmts", + "submodule_header_stmts", "module_header_stmts", "submodule_stmt", + "module_stmt" }; + + @Override + public String getGrammarFileName() { + return "yangParser.g4"; + } + + @Override + public String[] getTokenNames() { + return tokenNames; + } + + @Override + public String[] getRuleNames() { + return ruleNames; + } + + @Override + public ATN getATN() { + return _ATN; + } + + public YangParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this, _ATN, _decisionToDFA, + _sharedContextCache); + } + + public static class YangContext extends ParserRuleContext { + public Submodule_stmtContext submodule_stmt() { + return getRuleContext(Submodule_stmtContext.class, 0); + } + + public Module_stmtContext module_stmt() { + return getRuleContext(Module_stmtContext.class, 0); + } + + public YangContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_yang; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterYang(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitYang(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitYang(this); + else + return visitor.visitChildren(this); + } + } + + public final YangContext yang() throws RecognitionException { + YangContext _localctx = new YangContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_yang); + try { + setState(214); + switch (_input.LA(1)) { + case MODULE_KEYWORD: + enterOuterAlt(_localctx, 1); + { + setState(212); + module_stmt(); + } + break; + case SUBMODULE_KEYWORD: + enterOuterAlt(_localctx, 2); + { + setState(213); + submodule_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class StringContext extends ParserRuleContext { + public List PLUS() { + return getTokens(YangParser.PLUS); + } + + public TerminalNode STRING(int i) { + return getToken(YangParser.STRING, i); + } + + public TerminalNode PLUS(int i) { + return getToken(YangParser.PLUS, i); + } + + public List STRING() { + return getTokens(YangParser.STRING); + } + + public StringContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_string; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterString(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitString(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitString(this); + else + return visitor.visitChildren(this); + } + } + + public final StringContext string() throws RecognitionException { + StringContext _localctx = new StringContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_string); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(216); + match(STRING); + setState(221); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == PLUS) { + { + { + setState(217); + match(PLUS); + setState(218); + match(STRING); + } + } + setState(223); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Identifier_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode IDENTIFIER() { + return getToken(YangParser.IDENTIFIER, 0); + } + + public Identifier_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_identifier_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterIdentifier_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitIdentifier_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitIdentifier_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Identifier_stmtContext identifier_stmt() + throws RecognitionException { + Identifier_stmtContext _localctx = new Identifier_stmtContext(_ctx, + getState()); + enterRule(_localctx, 4, RULE_identifier_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(224); + match(IDENTIFIER); + setState(226); + _la = _input.LA(1); + if (_la == STRING) { + { + setState(225); + string(); + } + } + + setState(228); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class StmtendContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public Identifier_stmtContext identifier_stmt() { + return getRuleContext(Identifier_stmtContext.class, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public StmtendContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_stmtend; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterStmtend(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitStmtend(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitStmtend(this); + else + return visitor.visitChildren(this); + } + } + + public final StmtendContext stmtend() throws RecognitionException { + StmtendContext _localctx = new StmtendContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_stmtend); + int _la; + try { + setState(239); + switch (_input.LA(1)) { + case SEMICOLON: + enterOuterAlt(_localctx, 1); + { + { + setState(230); + match(SEMICOLON); + setState(232); + switch (getInterpreter().adaptivePredict(_input, 3, + _ctx)) { + case 1: { + setState(231); + identifier_stmt(); + } + break; + } + } + } + break; + case LEFT_BRACE: + enterOuterAlt(_localctx, 2); + { + { + setState(234); + match(LEFT_BRACE); + setState(236); + _la = _input.LA(1); + if (_la == IDENTIFIER) { + { + setState(235); + identifier_stmt(); + } + } + + setState(238); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Deviate_replace_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Units_stmtContext units_stmt(int i) { + return getRuleContext(Units_stmtContext.class, i); + } + + public Default_stmtContext default_stmt(int i) { + return getRuleContext(Default_stmtContext.class, i); + } + + public List units_stmt() { + return getRuleContexts(Units_stmtContext.class); + } + + public List max_elements_stmt() { + return getRuleContexts(Max_elements_stmtContext.class); + } + + public Type_stmtContext type_stmt(int i) { + return getRuleContext(Type_stmtContext.class, i); + } + + public TerminalNode DEVIATE_KEYWORD() { + return getToken(YangParser.DEVIATE_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public List mandatory_stmt() { + return getRuleContexts(Mandatory_stmtContext.class); + } + + public List type_stmt() { + return getRuleContexts(Type_stmtContext.class); + } + + public Min_elements_stmtContext min_elements_stmt(int i) { + return getRuleContext(Min_elements_stmtContext.class, i); + } + + public List default_stmt() { + return getRuleContexts(Default_stmtContext.class); + } + + public Mandatory_stmtContext mandatory_stmt(int i) { + return getRuleContext(Mandatory_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List min_elements_stmt() { + return getRuleContexts(Min_elements_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public Max_elements_stmtContext max_elements_stmt(int i) { + return getRuleContext(Max_elements_stmtContext.class, i); + } + + public Deviate_replace_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_deviate_replace_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterDeviate_replace_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitDeviate_replace_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitDeviate_replace_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Deviate_replace_stmtContext deviate_replace_stmt() + throws RecognitionException { + Deviate_replace_stmtContext _localctx = new Deviate_replace_stmtContext( + _ctx, getState()); + enterRule(_localctx, 8, RULE_deviate_replace_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(241); + match(DEVIATE_KEYWORD); + setState(242); + string(); + setState(258); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(243); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(244); + match(LEFT_BRACE); + setState(254); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 13)) & ~0x3f) == 0 && ((1L << (_la - 13)) & ((1L << (UNITS_KEYWORD - 13)) + | (1L << (TYPE_KEYWORD - 13)) + | (1L << (MIN_ELEMENTS_KEYWORD - 13)) + | (1L << (MAX_ELEMENTS_KEYWORD - 13)) + | (1L << (MANDATORY_KEYWORD - 13)) + | (1L << (DEFAULT_KEYWORD - 13)) | (1L << (CONFIG_KEYWORD - 13)))) != 0)) { + { + setState(252); + switch (_input.LA(1)) { + case TYPE_KEYWORD: { + setState(245); + type_stmt(); + } + break; + case UNITS_KEYWORD: { + setState(246); + units_stmt(); + } + break; + case DEFAULT_KEYWORD: { + setState(247); + default_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(248); + config_stmt(); + } + break; + case MANDATORY_KEYWORD: { + setState(249); + mandatory_stmt(); + } + break; + case MIN_ELEMENTS_KEYWORD: { + setState(250); + min_elements_stmt(); + } + break; + case MAX_ELEMENTS_KEYWORD: { + setState(251); + max_elements_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(256); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(257); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Deviate_delete_stmtContext extends ParserRuleContext { + public Units_stmtContext units_stmt(int i) { + return getRuleContext(Units_stmtContext.class, i); + } + + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List default_stmt() { + return getRuleContexts(Default_stmtContext.class); + } + + public Default_stmtContext default_stmt(int i) { + return getRuleContext(Default_stmtContext.class, i); + } + + public List units_stmt() { + return getRuleContexts(Units_stmtContext.class); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List unique_stmt() { + return getRuleContexts(Unique_stmtContext.class); + } + + public TerminalNode DEVIATE_KEYWORD() { + return getToken(YangParser.DEVIATE_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Unique_stmtContext unique_stmt(int i) { + return getRuleContext(Unique_stmtContext.class, i); + } + + public Deviate_delete_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_deviate_delete_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterDeviate_delete_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitDeviate_delete_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitDeviate_delete_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Deviate_delete_stmtContext deviate_delete_stmt() + throws RecognitionException { + Deviate_delete_stmtContext _localctx = new Deviate_delete_stmtContext( + _ctx, getState()); + enterRule(_localctx, 10, RULE_deviate_delete_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(260); + match(DEVIATE_KEYWORD); + setState(261); + string(); + setState(274); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(262); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(263); + match(LEFT_BRACE); + setState(270); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << UNITS_KEYWORD) + | (1L << UNIQUE_KEYWORD) | (1L << MUST_KEYWORD) | (1L << DEFAULT_KEYWORD))) != 0)) { + { + setState(268); + switch (_input.LA(1)) { + case UNITS_KEYWORD: { + setState(264); + units_stmt(); + } + break; + case MUST_KEYWORD: { + setState(265); + must_stmt(); + } + break; + case UNIQUE_KEYWORD: { + setState(266); + unique_stmt(); + } + break; + case DEFAULT_KEYWORD: { + setState(267); + default_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(272); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(273); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Deviate_add_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Units_stmtContext units_stmt(int i) { + return getRuleContext(Units_stmtContext.class, i); + } + + public Default_stmtContext default_stmt(int i) { + return getRuleContext(Default_stmtContext.class, i); + } + + public List units_stmt() { + return getRuleContexts(Units_stmtContext.class); + } + + public List max_elements_stmt() { + return getRuleContexts(Max_elements_stmtContext.class); + } + + public TerminalNode DEVIATE_KEYWORD() { + return getToken(YangParser.DEVIATE_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public List mandatory_stmt() { + return getRuleContexts(Mandatory_stmtContext.class); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Min_elements_stmtContext min_elements_stmt(int i) { + return getRuleContext(Min_elements_stmtContext.class, i); + } + + public List default_stmt() { + return getRuleContexts(Default_stmtContext.class); + } + + public Mandatory_stmtContext mandatory_stmt(int i) { + return getRuleContext(Mandatory_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List min_elements_stmt() { + return getRuleContexts(Min_elements_stmtContext.class); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List unique_stmt() { + return getRuleContexts(Unique_stmtContext.class); + } + + public Max_elements_stmtContext max_elements_stmt(int i) { + return getRuleContext(Max_elements_stmtContext.class, i); + } + + public Unique_stmtContext unique_stmt(int i) { + return getRuleContext(Unique_stmtContext.class, i); + } + + public Deviate_add_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_deviate_add_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterDeviate_add_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitDeviate_add_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitDeviate_add_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Deviate_add_stmtContext deviate_add_stmt() + throws RecognitionException { + Deviate_add_stmtContext _localctx = new Deviate_add_stmtContext(_ctx, + getState()); + enterRule(_localctx, 12, RULE_deviate_add_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(276); + match(DEVIATE_KEYWORD); + setState(277); + string(); + setState(294); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(278); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(279); + match(LEFT_BRACE); + setState(290); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 13)) & ~0x3f) == 0 && ((1L << (_la - 13)) & ((1L << (UNITS_KEYWORD - 13)) + | (1L << (UNIQUE_KEYWORD - 13)) + | (1L << (MUST_KEYWORD - 13)) + | (1L << (MIN_ELEMENTS_KEYWORD - 13)) + | (1L << (MAX_ELEMENTS_KEYWORD - 13)) + | (1L << (MANDATORY_KEYWORD - 13)) + | (1L << (DEFAULT_KEYWORD - 13)) | (1L << (CONFIG_KEYWORD - 13)))) != 0)) { + { + setState(288); + switch (_input.LA(1)) { + case UNITS_KEYWORD: { + setState(280); + units_stmt(); + } + break; + case MUST_KEYWORD: { + setState(281); + must_stmt(); + } + break; + case UNIQUE_KEYWORD: { + setState(282); + unique_stmt(); + } + break; + case DEFAULT_KEYWORD: { + setState(283); + default_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(284); + config_stmt(); + } + break; + case MANDATORY_KEYWORD: { + setState(285); + mandatory_stmt(); + } + break; + case MIN_ELEMENTS_KEYWORD: { + setState(286); + min_elements_stmt(); + } + break; + case MAX_ELEMENTS_KEYWORD: { + setState(287); + max_elements_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(292); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(293); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Deviate_not_supported_stmtContext extends + ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public Identifier_stmtContext identifier_stmt() { + return getRuleContext(Identifier_stmtContext.class, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode DEVIATE_KEYWORD() { + return getToken(YangParser.DEVIATE_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Deviate_not_supported_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_deviate_not_supported_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterDeviate_not_supported_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .exitDeviate_not_supported_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitDeviate_not_supported_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Deviate_not_supported_stmtContext deviate_not_supported_stmt() + throws RecognitionException { + Deviate_not_supported_stmtContext _localctx = new Deviate_not_supported_stmtContext( + _ctx, getState()); + enterRule(_localctx, 14, RULE_deviate_not_supported_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(296); + match(DEVIATE_KEYWORD); + setState(297); + string(); + setState(304); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(298); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(299); + match(LEFT_BRACE); + setState(301); + _la = _input.LA(1); + if (_la == IDENTIFIER) { + { + setState(300); + identifier_stmt(); + } + } + + setState(303); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Deviation_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public TerminalNode DEVIATION_KEYWORD() { + return getToken(YangParser.DEVIATION_KEYWORD, 0); + } + + public Deviate_replace_stmtContext deviate_replace_stmt(int i) { + return getRuleContext(Deviate_replace_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Deviate_delete_stmtContext deviate_delete_stmt(int i) { + return getRuleContext(Deviate_delete_stmtContext.class, i); + } + + public List deviate_delete_stmt() { + return getRuleContexts(Deviate_delete_stmtContext.class); + } + + public Deviate_add_stmtContext deviate_add_stmt(int i) { + return getRuleContext(Deviate_add_stmtContext.class, i); + } + + public List deviate_add_stmt() { + return getRuleContexts(Deviate_add_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List deviate_replace_stmt() { + return getRuleContexts(Deviate_replace_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public List deviate_not_supported_stmt() { + return getRuleContexts(Deviate_not_supported_stmtContext.class); + } + + public Deviate_not_supported_stmtContext deviate_not_supported_stmt( + int i) { + return getRuleContext(Deviate_not_supported_stmtContext.class, i); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Deviation_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_deviation_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterDeviation_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitDeviation_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitDeviation_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Deviation_stmtContext deviation_stmt() + throws RecognitionException { + Deviation_stmtContext _localctx = new Deviation_stmtContext(_ctx, + getState()); + enterRule(_localctx, 16, RULE_deviation_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(306); + match(DEVIATION_KEYWORD); + setState(307); + string(); + setState(308); + match(LEFT_BRACE); + setState(315); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(315); + switch (getInterpreter().adaptivePredict(_input, 17, + _ctx)) { + case 1: { + setState(309); + description_stmt(); + } + break; + + case 2: { + setState(310); + reference_stmt(); + } + break; + + case 3: { + setState(311); + deviate_not_supported_stmt(); + } + break; + + case 4: { + setState(312); + deviate_add_stmt(); + } + break; + + case 5: { + setState(313); + deviate_replace_stmt(); + } + break; + + case 6: { + setState(314); + deviate_delete_stmt(); + } + break; + } + } + setState(317); + _errHandler.sync(this); + _la = _input.LA(1); + } while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << REFERENCE_KEYWORD) + | (1L << DEVIATE_KEYWORD) | (1L << DESCRIPTION_KEYWORD))) != 0)); + setState(319); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Notification_stmtContext extends ParserRuleContext { + public List grouping_stmt() { + return getRuleContexts(Grouping_stmtContext.class); + } + + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Typedef_stmtContext typedef_stmt(int i) { + return getRuleContext(Typedef_stmtContext.class, i); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Grouping_stmtContext grouping_stmt(int i) { + return getRuleContext(Grouping_stmtContext.class, i); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public List typedef_stmt() { + return getRuleContexts(Typedef_stmtContext.class); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public TerminalNode NOTIFICATION_KEYWORD() { + return getToken(YangParser.NOTIFICATION_KEYWORD, 0); + } + + public Notification_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_notification_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterNotification_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitNotification_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitNotification_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Notification_stmtContext notification_stmt() + throws RecognitionException { + Notification_stmtContext _localctx = new Notification_stmtContext(_ctx, + getState()); + enterRule(_localctx, 18, RULE_notification_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(321); + match(NOTIFICATION_KEYWORD); + setState(322); + string(); + setState(338); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(323); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(324); + match(LEFT_BRACE); + setState(334); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (USES_KEYWORD - 12)) + | (1L << (TYPEDEF_KEYWORD - 12)) + | (1L << (STATUS_KEYWORD - 12)) + | (1L << (REFERENCE_KEYWORD - 12)) + | (1L << (LIST_KEYWORD - 12)) + | (1L << (LEAF_LIST_KEYWORD - 12)) + | (1L << (LEAF_KEYWORD - 12)) + | (1L << (IF_FEATURE_KEYWORD - 12)) + | (1L << (GROUPING_KEYWORD - 12)) + | (1L << (DESCRIPTION_KEYWORD - 12)) + | (1L << (CONTAINER_KEYWORD - 12)) + | (1L << (CHOICE_KEYWORD - 12)) | (1L << (ANYXML_KEYWORD - 12)))) != 0)) { + { + setState(332); + switch (_input.LA(1)) { + case IF_FEATURE_KEYWORD: { + setState(325); + if_feature_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(326); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(327); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(328); + reference_stmt(); + } + break; + case TYPEDEF_KEYWORD: { + setState(329); + typedef_stmt(); + } + break; + case GROUPING_KEYWORD: { + setState(330); + grouping_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(331); + data_def_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(336); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(337); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Output_stmtContext extends ParserRuleContext { + public List grouping_stmt() { + return getRuleContexts(Grouping_stmtContext.class); + } + + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Typedef_stmtContext typedef_stmt(int i) { + return getRuleContext(Typedef_stmtContext.class, i); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public Grouping_stmtContext grouping_stmt(int i) { + return getRuleContext(Grouping_stmtContext.class, i); + } + + public TerminalNode OUTPUT_KEYWORD() { + return getToken(YangParser.OUTPUT_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public List typedef_stmt() { + return getRuleContexts(Typedef_stmtContext.class); + } + + public Output_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_output_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterOutput_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitOutput_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitOutput_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Output_stmtContext output_stmt() throws RecognitionException { + Output_stmtContext _localctx = new Output_stmtContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_output_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(340); + match(OUTPUT_KEYWORD); + setState(341); + match(LEFT_BRACE); + setState(345); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(345); + switch (_input.LA(1)) { + case TYPEDEF_KEYWORD: { + setState(342); + typedef_stmt(); + } + break; + case GROUPING_KEYWORD: { + setState(343); + grouping_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(344); + data_def_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(347); + _errHandler.sync(this); + _la = _input.LA(1); + } while (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (USES_KEYWORD - 12)) + | (1L << (TYPEDEF_KEYWORD - 12)) + | (1L << (LIST_KEYWORD - 12)) + | (1L << (LEAF_LIST_KEYWORD - 12)) + | (1L << (LEAF_KEYWORD - 12)) + | (1L << (GROUPING_KEYWORD - 12)) + | (1L << (CONTAINER_KEYWORD - 12)) + | (1L << (CHOICE_KEYWORD - 12)) | (1L << (ANYXML_KEYWORD - 12)))) != 0)); + setState(349); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Input_stmtContext extends ParserRuleContext { + public List grouping_stmt() { + return getRuleContexts(Grouping_stmtContext.class); + } + + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Typedef_stmtContext typedef_stmt(int i) { + return getRuleContext(Typedef_stmtContext.class, i); + } + + public TerminalNode INPUT_KEYWORD() { + return getToken(YangParser.INPUT_KEYWORD, 0); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public Grouping_stmtContext grouping_stmt(int i) { + return getRuleContext(Grouping_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public List typedef_stmt() { + return getRuleContexts(Typedef_stmtContext.class); + } + + public Input_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_input_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterInput_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitInput_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitInput_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Input_stmtContext input_stmt() throws RecognitionException { + Input_stmtContext _localctx = new Input_stmtContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_input_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(351); + match(INPUT_KEYWORD); + setState(352); + match(LEFT_BRACE); + setState(356); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(356); + switch (_input.LA(1)) { + case TYPEDEF_KEYWORD: { + setState(353); + typedef_stmt(); + } + break; + case GROUPING_KEYWORD: { + setState(354); + grouping_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(355); + data_def_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(358); + _errHandler.sync(this); + _la = _input.LA(1); + } while (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (USES_KEYWORD - 12)) + | (1L << (TYPEDEF_KEYWORD - 12)) + | (1L << (LIST_KEYWORD - 12)) + | (1L << (LEAF_LIST_KEYWORD - 12)) + | (1L << (LEAF_KEYWORD - 12)) + | (1L << (GROUPING_KEYWORD - 12)) + | (1L << (CONTAINER_KEYWORD - 12)) + | (1L << (CHOICE_KEYWORD - 12)) | (1L << (ANYXML_KEYWORD - 12)))) != 0)); + setState(360); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Rpc_stmtContext extends ParserRuleContext { + public List grouping_stmt() { + return getRuleContexts(Grouping_stmtContext.class); + } + + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Output_stmtContext output_stmt(int i) { + return getRuleContext(Output_stmtContext.class, i); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Typedef_stmtContext typedef_stmt(int i) { + return getRuleContext(Typedef_stmtContext.class, i); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Grouping_stmtContext grouping_stmt(int i) { + return getRuleContext(Grouping_stmtContext.class, i); + } + + public Input_stmtContext input_stmt(int i) { + return getRuleContext(Input_stmtContext.class, i); + } + + public List input_stmt() { + return getRuleContexts(Input_stmtContext.class); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public List typedef_stmt() { + return getRuleContexts(Typedef_stmtContext.class); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public List output_stmt() { + return getRuleContexts(Output_stmtContext.class); + } + + public TerminalNode RPC_KEYWORD() { + return getToken(YangParser.RPC_KEYWORD, 0); + } + + public Rpc_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_rpc_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRpc_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRpc_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRpc_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Rpc_stmtContext rpc_stmt() throws RecognitionException { + Rpc_stmtContext _localctx = new Rpc_stmtContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_rpc_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(362); + match(RPC_KEYWORD); + setState(363); + string(); + setState(380); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(364); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(365); + match(LEFT_BRACE); + setState(376); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << TYPEDEF_KEYWORD) + | (1L << STATUS_KEYWORD) + | (1L << REFERENCE_KEYWORD) + | (1L << OUTPUT_KEYWORD) + | (1L << INPUT_KEYWORD) + | (1L << IF_FEATURE_KEYWORD) + | (1L << GROUPING_KEYWORD) | (1L << DESCRIPTION_KEYWORD))) != 0)) { + { + setState(374); + switch (_input.LA(1)) { + case IF_FEATURE_KEYWORD: { + setState(366); + if_feature_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(367); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(368); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(369); + reference_stmt(); + } + break; + case TYPEDEF_KEYWORD: { + setState(370); + typedef_stmt(); + } + break; + case GROUPING_KEYWORD: { + setState(371); + grouping_stmt(); + } + break; + case INPUT_KEYWORD: { + setState(372); + input_stmt(); + } + break; + case OUTPUT_KEYWORD: { + setState(373); + output_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(378); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(379); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class When_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public TerminalNode WHEN_KEYWORD() { + return getToken(YangParser.WHEN_KEYWORD, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public When_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_when_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterWhen_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitWhen_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitWhen_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final When_stmtContext when_stmt() throws RecognitionException { + When_stmtContext _localctx = new When_stmtContext(_ctx, getState()); + enterRule(_localctx, 26, RULE_when_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(382); + match(WHEN_KEYWORD); + setState(383); + string(); + setState(394); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(384); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(385); + match(LEFT_BRACE); + setState(390); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == REFERENCE_KEYWORD + || _la == DESCRIPTION_KEYWORD) { + { + setState(388); + switch (_input.LA(1)) { + case DESCRIPTION_KEYWORD: { + setState(386); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(387); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(392); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(393); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Augment_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public List case_stmt() { + return getRuleContexts(Case_stmtContext.class); + } + + public TerminalNode AUGMENT_KEYWORD() { + return getToken(YangParser.AUGMENT_KEYWORD, 0); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Case_stmtContext case_stmt(int i) { + return getRuleContext(Case_stmtContext.class, i); + } + + public Augment_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_augment_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterAugment_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitAugment_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitAugment_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Augment_stmtContext augment_stmt() throws RecognitionException { + Augment_stmtContext _localctx = new Augment_stmtContext(_ctx, + getState()); + enterRule(_localctx, 28, RULE_augment_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(396); + match(AUGMENT_KEYWORD); + setState(397); + string(); + setState(398); + match(LEFT_BRACE); + setState(407); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(407); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(399); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(400); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(401); + if_feature_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(402); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(403); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(404); + reference_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(405); + data_def_stmt(); + } + break; + case CASE_KEYWORD: { + setState(406); + case_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(409); + _errHandler.sync(this); + _la = _input.LA(1); + } while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (USES_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (LIST_KEYWORD - 10)) + | (1L << (LEAF_LIST_KEYWORD - 10)) + | (1L << (LEAF_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (CONTAINER_KEYWORD - 10)) + | (1L << (CHOICE_KEYWORD - 10)) + | (1L << (CASE_KEYWORD - 10)) + | (1L << (ANYXML_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)); + setState(411); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Uses_augment_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public List case_stmt() { + return getRuleContexts(Case_stmtContext.class); + } + + public TerminalNode AUGMENT_KEYWORD() { + return getToken(YangParser.AUGMENT_KEYWORD, 0); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Case_stmtContext case_stmt(int i) { + return getRuleContext(Case_stmtContext.class, i); + } + + public Uses_augment_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_uses_augment_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterUses_augment_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitUses_augment_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitUses_augment_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Uses_augment_stmtContext uses_augment_stmt() + throws RecognitionException { + Uses_augment_stmtContext _localctx = new Uses_augment_stmtContext(_ctx, + getState()); + enterRule(_localctx, 30, RULE_uses_augment_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(413); + match(AUGMENT_KEYWORD); + setState(414); + string(); + setState(415); + match(LEFT_BRACE); + setState(424); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(424); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(416); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(417); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(418); + if_feature_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(419); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(420); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(421); + reference_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(422); + data_def_stmt(); + } + break; + case CASE_KEYWORD: { + setState(423); + case_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(426); + _errHandler.sync(this); + _la = _input.LA(1); + } while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (USES_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (LIST_KEYWORD - 10)) + | (1L << (LEAF_LIST_KEYWORD - 10)) + | (1L << (LEAF_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (CONTAINER_KEYWORD - 10)) + | (1L << (CHOICE_KEYWORD - 10)) + | (1L << (CASE_KEYWORD - 10)) + | (1L << (ANYXML_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)); + setState(428); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refine_anyxml_stmtsContext extends ParserRuleContext { + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Mandatory_stmtContext mandatory_stmt(int i) { + return getRuleContext(Mandatory_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public List mandatory_stmt() { + return getRuleContexts(Mandatory_stmtContext.class); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Refine_anyxml_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refine_anyxml_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRefine_anyxml_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRefine_anyxml_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefine_anyxml_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Refine_anyxml_stmtsContext refine_anyxml_stmts() + throws RecognitionException { + Refine_anyxml_stmtsContext _localctx = new Refine_anyxml_stmtsContext( + _ctx, getState()); + enterRule(_localctx, 32, RULE_refine_anyxml_stmts); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(437); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 37, _ctx); + while (_alt != 2 && _alt != -1) { + if (_alt == 1) { + { + setState(435); + switch (_input.LA(1)) { + case MUST_KEYWORD: { + setState(430); + must_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(431); + config_stmt(); + } + break; + case MANDATORY_KEYWORD: { + setState(432); + mandatory_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(433); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(434); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(439); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 37, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refine_case_stmtsContext extends ParserRuleContext { + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Refine_case_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refine_case_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRefine_case_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRefine_case_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefine_case_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Refine_case_stmtsContext refine_case_stmts() + throws RecognitionException { + Refine_case_stmtsContext _localctx = new Refine_case_stmtsContext(_ctx, + getState()); + enterRule(_localctx, 34, RULE_refine_case_stmts); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(444); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 39, _ctx); + while (_alt != 2 && _alt != -1) { + if (_alt == 1) { + { + setState(442); + switch (_input.LA(1)) { + case DESCRIPTION_KEYWORD: { + setState(440); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(441); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(446); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 39, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refine_choice_stmtsContext extends ParserRuleContext { + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public List default_stmt() { + return getRuleContexts(Default_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Default_stmtContext default_stmt(int i) { + return getRuleContext(Default_stmtContext.class, i); + } + + public Mandatory_stmtContext mandatory_stmt(int i) { + return getRuleContext(Mandatory_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public List mandatory_stmt() { + return getRuleContexts(Mandatory_stmtContext.class); + } + + public Refine_choice_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refine_choice_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRefine_choice_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRefine_choice_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefine_choice_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Refine_choice_stmtsContext refine_choice_stmts() + throws RecognitionException { + Refine_choice_stmtsContext _localctx = new Refine_choice_stmtsContext( + _ctx, getState()); + enterRule(_localctx, 36, RULE_refine_choice_stmts); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(454); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 41, _ctx); + while (_alt != 2 && _alt != -1) { + if (_alt == 1) { + { + setState(452); + switch (_input.LA(1)) { + case DEFAULT_KEYWORD: { + setState(447); + default_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(448); + config_stmt(); + } + break; + case MANDATORY_KEYWORD: { + setState(449); + mandatory_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(450); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(451); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(456); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 41, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refine_list_stmtsContext extends ParserRuleContext { + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public List min_elements_stmt() { + return getRuleContexts(Min_elements_stmtContext.class); + } + + public List max_elements_stmt() { + return getRuleContexts(Max_elements_stmtContext.class); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public Max_elements_stmtContext max_elements_stmt(int i) { + return getRuleContext(Max_elements_stmtContext.class, i); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Min_elements_stmtContext min_elements_stmt(int i) { + return getRuleContext(Min_elements_stmtContext.class, i); + } + + public Refine_list_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refine_list_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRefine_list_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRefine_list_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefine_list_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Refine_list_stmtsContext refine_list_stmts() + throws RecognitionException { + Refine_list_stmtsContext _localctx = new Refine_list_stmtsContext(_ctx, + getState()); + enterRule(_localctx, 38, RULE_refine_list_stmts); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(465); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 43, _ctx); + while (_alt != 2 && _alt != -1) { + if (_alt == 1) { + { + setState(463); + switch (_input.LA(1)) { + case MUST_KEYWORD: { + setState(457); + must_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(458); + config_stmt(); + } + break; + case MIN_ELEMENTS_KEYWORD: { + setState(459); + min_elements_stmt(); + } + break; + case MAX_ELEMENTS_KEYWORD: { + setState(460); + max_elements_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(461); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(462); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(467); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 43, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refine_leaf_list_stmtsContext extends ParserRuleContext { + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public List min_elements_stmt() { + return getRuleContexts(Min_elements_stmtContext.class); + } + + public List max_elements_stmt() { + return getRuleContexts(Max_elements_stmtContext.class); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public Max_elements_stmtContext max_elements_stmt(int i) { + return getRuleContext(Max_elements_stmtContext.class, i); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Min_elements_stmtContext min_elements_stmt(int i) { + return getRuleContext(Min_elements_stmtContext.class, i); + } + + public Refine_leaf_list_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refine_leaf_list_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterRefine_leaf_list_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .exitRefine_leaf_list_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefine_leaf_list_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Refine_leaf_list_stmtsContext refine_leaf_list_stmts() + throws RecognitionException { + Refine_leaf_list_stmtsContext _localctx = new Refine_leaf_list_stmtsContext( + _ctx, getState()); + enterRule(_localctx, 40, RULE_refine_leaf_list_stmts); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(476); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 45, _ctx); + while (_alt != 2 && _alt != -1) { + if (_alt == 1) { + { + setState(474); + switch (_input.LA(1)) { + case MUST_KEYWORD: { + setState(468); + must_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(469); + config_stmt(); + } + break; + case MIN_ELEMENTS_KEYWORD: { + setState(470); + min_elements_stmt(); + } + break; + case MAX_ELEMENTS_KEYWORD: { + setState(471); + max_elements_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(472); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(473); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(478); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 45, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refine_leaf_stmtsContext extends ParserRuleContext { + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public List default_stmt() { + return getRuleContexts(Default_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Default_stmtContext default_stmt(int i) { + return getRuleContext(Default_stmtContext.class, i); + } + + public Mandatory_stmtContext mandatory_stmt(int i) { + return getRuleContext(Mandatory_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public List mandatory_stmt() { + return getRuleContexts(Mandatory_stmtContext.class); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Refine_leaf_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refine_leaf_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRefine_leaf_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRefine_leaf_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefine_leaf_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Refine_leaf_stmtsContext refine_leaf_stmts() + throws RecognitionException { + Refine_leaf_stmtsContext _localctx = new Refine_leaf_stmtsContext(_ctx, + getState()); + enterRule(_localctx, 42, RULE_refine_leaf_stmts); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(487); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 47, _ctx); + while (_alt != 2 && _alt != -1) { + if (_alt == 1) { + { + setState(485); + switch (_input.LA(1)) { + case MUST_KEYWORD: { + setState(479); + must_stmt(); + } + break; + case DEFAULT_KEYWORD: { + setState(480); + default_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(481); + config_stmt(); + } + break; + case MANDATORY_KEYWORD: { + setState(482); + mandatory_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(483); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(484); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(489); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 47, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refine_container_stmtsContext extends ParserRuleContext { + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public List presence_stmt() { + return getRuleContexts(Presence_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public Presence_stmtContext presence_stmt(int i) { + return getRuleContext(Presence_stmtContext.class, i); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Refine_container_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refine_container_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterRefine_container_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .exitRefine_container_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefine_container_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Refine_container_stmtsContext refine_container_stmts() + throws RecognitionException { + Refine_container_stmtsContext _localctx = new Refine_container_stmtsContext( + _ctx, getState()); + enterRule(_localctx, 44, RULE_refine_container_stmts); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(497); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 49, _ctx); + while (_alt != 2 && _alt != -1) { + if (_alt == 1) { + { + setState(495); + switch (_input.LA(1)) { + case MUST_KEYWORD: { + setState(490); + must_stmt(); + } + break; + case PRESENCE_KEYWORD: { + setState(491); + presence_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(492); + config_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(493); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(494); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(499); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 49, _ctx); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refune_pomContext extends ParserRuleContext { + public Refine_list_stmtsContext refine_list_stmts() { + return getRuleContext(Refine_list_stmtsContext.class, 0); + } + + public Refine_choice_stmtsContext refine_choice_stmts() { + return getRuleContext(Refine_choice_stmtsContext.class, 0); + } + + public Refine_leaf_list_stmtsContext refine_leaf_list_stmts() { + return getRuleContext(Refine_leaf_list_stmtsContext.class, 0); + } + + public Refine_case_stmtsContext refine_case_stmts() { + return getRuleContext(Refine_case_stmtsContext.class, 0); + } + + public Refine_leaf_stmtsContext refine_leaf_stmts() { + return getRuleContext(Refine_leaf_stmtsContext.class, 0); + } + + public Refine_anyxml_stmtsContext refine_anyxml_stmts() { + return getRuleContext(Refine_anyxml_stmtsContext.class, 0); + } + + public Refine_container_stmtsContext refine_container_stmts() { + return getRuleContext(Refine_container_stmtsContext.class, 0); + } + + public Refune_pomContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refune_pom; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRefune_pom(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRefune_pom(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefune_pom(this); + else + return visitor.visitChildren(this); + } + } + + public final Refune_pomContext refune_pom() throws RecognitionException { + Refune_pomContext _localctx = new Refune_pomContext(_ctx, getState()); + enterRule(_localctx, 46, RULE_refune_pom); + try { + enterOuterAlt(_localctx, 1); + { + setState(507); + switch (getInterpreter().adaptivePredict(_input, 50, _ctx)) { + case 1: { + setState(500); + refine_container_stmts(); + } + break; + + case 2: { + setState(501); + refine_leaf_stmts(); + } + break; + + case 3: { + setState(502); + refine_leaf_list_stmts(); + } + break; + + case 4: { + setState(503); + refine_list_stmts(); + } + break; + + case 5: { + setState(504); + refine_choice_stmts(); + } + break; + + case 6: { + setState(505); + refine_case_stmts(); + } + break; + + case 7: { + setState(506); + refine_anyxml_stmts(); + } + break; + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Refine_stmtContext extends ParserRuleContext { + public List refune_pom() { + return getRuleContexts(Refune_pomContext.class); + } + + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Refune_pomContext refune_pom(int i) { + return getRuleContext(Refune_pomContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public TerminalNode REFINE_KEYWORD() { + return getToken(YangParser.REFINE_KEYWORD, 0); + } + + public Refine_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_refine_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRefine_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRefine_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRefine_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Refine_stmtContext refine_stmt() throws RecognitionException { + Refine_stmtContext _localctx = new Refine_stmtContext(_ctx, getState()); + enterRule(_localctx, 48, RULE_refine_stmt); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(509); + match(REFINE_KEYWORD); + setState(510); + string(); + setState(520); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(511); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(512); + match(LEFT_BRACE); + setState(514); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 51, + _ctx); + do { + switch (_alt) { + case 1: { + { + setState(513); + refune_pom(); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(516); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 51, + _ctx); + } while (_alt != 2 && _alt != -1); + setState(518); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Uses_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public List uses_augment_stmt() { + return getRuleContexts(Uses_augment_stmtContext.class); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode USES_KEYWORD() { + return getToken(YangParser.USES_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public Refine_stmtContext refine_stmt(int i) { + return getRuleContext(Refine_stmtContext.class, i); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Uses_augment_stmtContext uses_augment_stmt(int i) { + return getRuleContext(Uses_augment_stmtContext.class, i); + } + + public List refine_stmt() { + return getRuleContexts(Refine_stmtContext.class); + } + + public Uses_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_uses_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterUses_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitUses_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitUses_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Uses_stmtContext uses_stmt() throws RecognitionException { + Uses_stmtContext _localctx = new Uses_stmtContext(_ctx, getState()); + enterRule(_localctx, 50, RULE_uses_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(522); + match(USES_KEYWORD); + setState(523); + string(); + setState(540); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(524); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(525); + match(LEFT_BRACE); + setState(536); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFINE_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (AUGMENT_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)) { + { + setState(534); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(526); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(527); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(528); + if_feature_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(529); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(530); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(531); + reference_stmt(); + } + break; + case REFINE_KEYWORD: { + setState(532); + refine_stmt(); + } + break; + case AUGMENT_KEYWORD: { + setState(533); + uses_augment_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(538); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(539); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Anyxml_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public TerminalNode ANYXML_KEYWORD() { + return getToken(YangParser.ANYXML_KEYWORD, 0); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List mandatory_stmt() { + return getRuleContexts(Mandatory_stmtContext.class); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public Mandatory_stmtContext mandatory_stmt(int i) { + return getRuleContext(Mandatory_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Anyxml_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_anyxml_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterAnyxml_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitAnyxml_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitAnyxml_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Anyxml_stmtContext anyxml_stmt() throws RecognitionException { + Anyxml_stmtContext _localctx = new Anyxml_stmtContext(_ctx, getState()); + enterRule(_localctx, 52, RULE_anyxml_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(542); + match(ANYXML_KEYWORD); + setState(543); + string(); + setState(561); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(544); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(545); + match(LEFT_BRACE); + setState(557); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (MUST_KEYWORD - 10)) + | (1L << (MANDATORY_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (CONFIG_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)) { + { + setState(555); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(546); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(547); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(548); + if_feature_stmt(); + } + break; + case MUST_KEYWORD: { + setState(549); + must_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(550); + config_stmt(); + } + break; + case MANDATORY_KEYWORD: { + setState(551); + mandatory_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(552); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(553); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(554); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(559); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(560); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Case_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public TerminalNode CASE_KEYWORD() { + return getToken(YangParser.CASE_KEYWORD, 0); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Case_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_case_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterCase_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitCase_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitCase_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Case_stmtContext case_stmt() throws RecognitionException { + Case_stmtContext _localctx = new Case_stmtContext(_ctx, getState()); + enterRule(_localctx, 54, RULE_case_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(563); + match(CASE_KEYWORD); + setState(564); + string(); + setState(580); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(565); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(566); + match(LEFT_BRACE); + setState(576); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (USES_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (LIST_KEYWORD - 10)) + | (1L << (LEAF_LIST_KEYWORD - 10)) + | (1L << (LEAF_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (CONTAINER_KEYWORD - 10)) + | (1L << (CHOICE_KEYWORD - 10)) + | (1L << (ANYXML_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)) { + { + setState(574); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(567); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(568); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(569); + if_feature_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(570); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(571); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(572); + reference_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(573); + data_def_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(578); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(579); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Short_case_stmtContext extends ParserRuleContext { + public Anyxml_stmtContext anyxml_stmt() { + return getRuleContext(Anyxml_stmtContext.class, 0); + } + + public List_stmtContext list_stmt() { + return getRuleContext(List_stmtContext.class, 0); + } + + public Leaf_stmtContext leaf_stmt() { + return getRuleContext(Leaf_stmtContext.class, 0); + } + + public Container_stmtContext container_stmt() { + return getRuleContext(Container_stmtContext.class, 0); + } + + public Leaf_list_stmtContext leaf_list_stmt() { + return getRuleContext(Leaf_list_stmtContext.class, 0); + } + + public Short_case_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_short_case_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterShort_case_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitShort_case_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitShort_case_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Short_case_stmtContext short_case_stmt() + throws RecognitionException { + Short_case_stmtContext _localctx = new Short_case_stmtContext(_ctx, + getState()); + enterRule(_localctx, 56, RULE_short_case_stmt); + try { + setState(587); + switch (_input.LA(1)) { + case CONTAINER_KEYWORD: + enterOuterAlt(_localctx, 1); + { + setState(582); + container_stmt(); + } + break; + case LEAF_KEYWORD: + enterOuterAlt(_localctx, 2); + { + setState(583); + leaf_stmt(); + } + break; + case LEAF_LIST_KEYWORD: + enterOuterAlt(_localctx, 3); + { + setState(584); + leaf_list_stmt(); + } + break; + case LIST_KEYWORD: + enterOuterAlt(_localctx, 4); + { + setState(585); + list_stmt(); + } + break; + case ANYXML_KEYWORD: + enterOuterAlt(_localctx, 5); + { + setState(586); + anyxml_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Choice_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Default_stmtContext default_stmt(int i) { + return getRuleContext(Default_stmtContext.class, i); + } + + public TerminalNode CHOICE_KEYWORD() { + return getToken(YangParser.CHOICE_KEYWORD, 0); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public List case_stmt() { + return getRuleContexts(Case_stmtContext.class); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List mandatory_stmt() { + return getRuleContexts(Mandatory_stmtContext.class); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List default_stmt() { + return getRuleContexts(Default_stmtContext.class); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public Mandatory_stmtContext mandatory_stmt(int i) { + return getRuleContext(Mandatory_stmtContext.class, i); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public Short_case_stmtContext short_case_stmt(int i) { + return getRuleContext(Short_case_stmtContext.class, i); + } + + public List short_case_stmt() { + return getRuleContexts(Short_case_stmtContext.class); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Case_stmtContext case_stmt(int i) { + return getRuleContext(Case_stmtContext.class, i); + } + + public Choice_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_choice_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterChoice_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitChoice_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitChoice_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Choice_stmtContext choice_stmt() throws RecognitionException { + Choice_stmtContext _localctx = new Choice_stmtContext(_ctx, getState()); + enterRule(_localctx, 58, RULE_choice_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(589); + match(CHOICE_KEYWORD); + setState(590); + string(); + setState(610); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(591); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(592); + match(LEFT_BRACE); + setState(606); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (MANDATORY_KEYWORD - 10)) + | (1L << (LIST_KEYWORD - 10)) + | (1L << (LEAF_LIST_KEYWORD - 10)) + | (1L << (LEAF_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (DEFAULT_KEYWORD - 10)) + | (1L << (CONTAINER_KEYWORD - 10)) + | (1L << (CONFIG_KEYWORD - 10)) + | (1L << (CASE_KEYWORD - 10)) + | (1L << (ANYXML_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)) { + { + setState(604); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(593); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(594); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(595); + if_feature_stmt(); + } + break; + case DEFAULT_KEYWORD: { + setState(596); + default_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(597); + config_stmt(); + } + break; + case MANDATORY_KEYWORD: { + setState(598); + mandatory_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(599); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(600); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(601); + reference_stmt(); + } + break; + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case ANYXML_KEYWORD: { + setState(602); + short_case_stmt(); + } + break; + case CASE_KEYWORD: { + setState(603); + case_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(608); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(609); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Unique_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode UNIQUE_KEYWORD() { + return getToken(YangParser.UNIQUE_KEYWORD, 0); + } + + public Unique_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_unique_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterUnique_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitUnique_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitUnique_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Unique_stmtContext unique_stmt() throws RecognitionException { + Unique_stmtContext _localctx = new Unique_stmtContext(_ctx, getState()); + enterRule(_localctx, 60, RULE_unique_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(612); + match(UNIQUE_KEYWORD); + setState(613); + string(); + setState(614); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Key_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode KEY_KEYWORD() { + return getToken(YangParser.KEY_KEYWORD, 0); + } + + public Key_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_key_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterKey_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitKey_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitKey_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Key_stmtContext key_stmt() throws RecognitionException { + Key_stmtContext _localctx = new Key_stmtContext(_ctx, getState()); + enterRule(_localctx, 62, RULE_key_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(616); + match(KEY_KEYWORD); + setState(617); + string(); + setState(618); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class List_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public List max_elements_stmt() { + return getRuleContexts(Max_elements_stmtContext.class); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public List typedef_stmt() { + return getRuleContexts(Typedef_stmtContext.class); + } + + public Min_elements_stmtContext min_elements_stmt(int i) { + return getRuleContext(Min_elements_stmtContext.class, i); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public List min_elements_stmt() { + return getRuleContexts(Min_elements_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Unique_stmtContext unique_stmt(int i) { + return getRuleContext(Unique_stmtContext.class, i); + } + + public List grouping_stmt() { + return getRuleContexts(Grouping_stmtContext.class); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Typedef_stmtContext typedef_stmt(int i) { + return getRuleContext(Typedef_stmtContext.class, i); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Ordered_by_stmtContext ordered_by_stmt(int i) { + return getRuleContext(Ordered_by_stmtContext.class, i); + } + + public Grouping_stmtContext grouping_stmt(int i) { + return getRuleContext(Grouping_stmtContext.class, i); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List ordered_by_stmt() { + return getRuleContexts(Ordered_by_stmtContext.class); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public TerminalNode LIST_KEYWORD() { + return getToken(YangParser.LIST_KEYWORD, 0); + } + + public Key_stmtContext key_stmt(int i) { + return getRuleContext(Key_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public List unique_stmt() { + return getRuleContexts(Unique_stmtContext.class); + } + + public Max_elements_stmtContext max_elements_stmt(int i) { + return getRuleContext(Max_elements_stmtContext.class, i); + } + + public List key_stmt() { + return getRuleContexts(Key_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public List_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_list_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterList_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitList_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitList_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final List_stmtContext list_stmt() throws RecognitionException { + List_stmtContext _localctx = new List_stmtContext(_ctx, getState()); + enterRule(_localctx, 64, RULE_list_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(620); + match(LIST_KEYWORD); + setState(621); + string(); + setState(622); + match(LEFT_BRACE); + setState(639); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(639); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(623); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(624); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(625); + if_feature_stmt(); + } + break; + case MUST_KEYWORD: { + setState(626); + must_stmt(); + } + break; + case KEY_KEYWORD: { + setState(627); + key_stmt(); + } + break; + case UNIQUE_KEYWORD: { + setState(628); + unique_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(629); + config_stmt(); + } + break; + case MIN_ELEMENTS_KEYWORD: { + setState(630); + min_elements_stmt(); + } + break; + case MAX_ELEMENTS_KEYWORD: { + setState(631); + max_elements_stmt(); + } + break; + case ORDERED_BY_KEYWORD: { + setState(632); + ordered_by_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(633); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(634); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(635); + reference_stmt(); + } + break; + case TYPEDEF_KEYWORD: { + setState(636); + typedef_stmt(); + } + break; + case GROUPING_KEYWORD: { + setState(637); + grouping_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(638); + data_def_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(641); + _errHandler.sync(this); + _la = _input.LA(1); + } while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (USES_KEYWORD - 10)) + | (1L << (UNIQUE_KEYWORD - 10)) + | (1L << (TYPEDEF_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (ORDERED_BY_KEYWORD - 10)) + | (1L << (MUST_KEYWORD - 10)) + | (1L << (MIN_ELEMENTS_KEYWORD - 10)) + | (1L << (MAX_ELEMENTS_KEYWORD - 10)) + | (1L << (LIST_KEYWORD - 10)) + | (1L << (LEAF_LIST_KEYWORD - 10)) + | (1L << (LEAF_KEYWORD - 10)) + | (1L << (KEY_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (GROUPING_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (CONTAINER_KEYWORD - 10)) + | (1L << (CONFIG_KEYWORD - 10)) + | (1L << (CHOICE_KEYWORD - 10)) + | (1L << (ANYXML_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)); + setState(643); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Leaf_list_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public Type_stmtContext type_stmt(int i) { + return getRuleContext(Type_stmtContext.class, i); + } + + public List max_elements_stmt() { + return getRuleContexts(Max_elements_stmtContext.class); + } + + public Min_elements_stmtContext min_elements_stmt(int i) { + return getRuleContext(Min_elements_stmtContext.class, i); + } + + public TerminalNode LEAF_LIST_KEYWORD() { + return getToken(YangParser.LEAF_LIST_KEYWORD, 0); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public List min_elements_stmt() { + return getRuleContexts(Min_elements_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Units_stmtContext units_stmt(int i) { + return getRuleContext(Units_stmtContext.class, i); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Ordered_by_stmtContext ordered_by_stmt(int i) { + return getRuleContext(Ordered_by_stmtContext.class, i); + } + + public List units_stmt() { + return getRuleContexts(Units_stmtContext.class); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List ordered_by_stmt() { + return getRuleContexts(Ordered_by_stmtContext.class); + } + + public List type_stmt() { + return getRuleContexts(Type_stmtContext.class); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public Max_elements_stmtContext max_elements_stmt(int i) { + return getRuleContext(Max_elements_stmtContext.class, i); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Leaf_list_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_leaf_list_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterLeaf_list_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitLeaf_list_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitLeaf_list_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Leaf_list_stmtContext leaf_list_stmt() + throws RecognitionException { + Leaf_list_stmtContext _localctx = new Leaf_list_stmtContext(_ctx, + getState()); + enterRule(_localctx, 66, RULE_leaf_list_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(645); + match(LEAF_LIST_KEYWORD); + setState(646); + string(); + setState(647); + match(LEFT_BRACE); + setState(663); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (UNITS_KEYWORD - 10)) + | (1L << (TYPE_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (ORDERED_BY_KEYWORD - 10)) + | (1L << (MUST_KEYWORD - 10)) + | (1L << (MIN_ELEMENTS_KEYWORD - 10)) + | (1L << (MAX_ELEMENTS_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (CONFIG_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)) { + { + setState(661); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(648); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(649); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(650); + if_feature_stmt(); + } + break; + case TYPE_KEYWORD: { + setState(651); + type_stmt(); + } + break; + case UNITS_KEYWORD: { + setState(652); + units_stmt(); + } + break; + case MUST_KEYWORD: { + setState(653); + must_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(654); + config_stmt(); + } + break; + case MIN_ELEMENTS_KEYWORD: { + setState(655); + min_elements_stmt(); + } + break; + case MAX_ELEMENTS_KEYWORD: { + setState(656); + max_elements_stmt(); + } + break; + case ORDERED_BY_KEYWORD: { + setState(657); + ordered_by_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(658); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(659); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(660); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(665); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(666); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Leaf_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public Type_stmtContext type_stmt(int i) { + return getRuleContext(Type_stmtContext.class, i); + } + + public List mandatory_stmt() { + return getRuleContexts(Mandatory_stmtContext.class); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public TerminalNode LEAF_KEYWORD() { + return getToken(YangParser.LEAF_KEYWORD, 0); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public Units_stmtContext units_stmt(int i) { + return getRuleContext(Units_stmtContext.class, i); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Default_stmtContext default_stmt(int i) { + return getRuleContext(Default_stmtContext.class, i); + } + + public List units_stmt() { + return getRuleContexts(Units_stmtContext.class); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List type_stmt() { + return getRuleContexts(Type_stmtContext.class); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List default_stmt() { + return getRuleContexts(Default_stmtContext.class); + } + + public Mandatory_stmtContext mandatory_stmt(int i) { + return getRuleContext(Mandatory_stmtContext.class, i); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Leaf_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_leaf_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterLeaf_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitLeaf_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitLeaf_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Leaf_stmtContext leaf_stmt() throws RecognitionException { + Leaf_stmtContext _localctx = new Leaf_stmtContext(_ctx, getState()); + enterRule(_localctx, 68, RULE_leaf_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(668); + match(LEAF_KEYWORD); + setState(669); + string(); + setState(670); + match(LEFT_BRACE); + setState(685); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (UNITS_KEYWORD - 10)) + | (1L << (TYPE_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (MUST_KEYWORD - 10)) + | (1L << (MANDATORY_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (DEFAULT_KEYWORD - 10)) + | (1L << (CONFIG_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)) { + { + setState(683); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(671); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(672); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(673); + if_feature_stmt(); + } + break; + case TYPE_KEYWORD: { + setState(674); + type_stmt(); + } + break; + case UNITS_KEYWORD: { + setState(675); + units_stmt(); + } + break; + case MUST_KEYWORD: { + setState(676); + must_stmt(); + } + break; + case DEFAULT_KEYWORD: { + setState(677); + default_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(678); + config_stmt(); + } + break; + case MANDATORY_KEYWORD: { + setState(679); + mandatory_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(680); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(681); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(682); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(687); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(688); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Container_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List when_stmt() { + return getRuleContexts(When_stmtContext.class); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public List typedef_stmt() { + return getRuleContexts(Typedef_stmtContext.class); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public Config_stmtContext config_stmt(int i) { + return getRuleContext(Config_stmtContext.class, i); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public When_stmtContext when_stmt(int i) { + return getRuleContext(When_stmtContext.class, i); + } + + public List grouping_stmt() { + return getRuleContexts(Grouping_stmtContext.class); + } + + public TerminalNode CONTAINER_KEYWORD() { + return getToken(YangParser.CONTAINER_KEYWORD, 0); + } + + public List presence_stmt() { + return getRuleContexts(Presence_stmtContext.class); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Typedef_stmtContext typedef_stmt(int i) { + return getRuleContext(Typedef_stmtContext.class, i); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Grouping_stmtContext grouping_stmt(int i) { + return getRuleContext(Grouping_stmtContext.class, i); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public Must_stmtContext must_stmt(int i) { + return getRuleContext(Must_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public Presence_stmtContext presence_stmt(int i) { + return getRuleContext(Presence_stmtContext.class, i); + } + + public List must_stmt() { + return getRuleContexts(Must_stmtContext.class); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List config_stmt() { + return getRuleContexts(Config_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Container_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_container_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterContainer_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitContainer_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitContainer_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Container_stmtContext container_stmt() + throws RecognitionException { + Container_stmtContext _localctx = new Container_stmtContext(_ctx, + getState()); + enterRule(_localctx, 70, RULE_container_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(690); + match(CONTAINER_KEYWORD); + setState(691); + string(); + setState(712); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(692); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(693); + match(LEFT_BRACE); + setState(708); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 10)) & ~0x3f) == 0 && ((1L << (_la - 10)) & ((1L << (WHEN_KEYWORD - 10)) + | (1L << (USES_KEYWORD - 10)) + | (1L << (TYPEDEF_KEYWORD - 10)) + | (1L << (STATUS_KEYWORD - 10)) + | (1L << (REFERENCE_KEYWORD - 10)) + | (1L << (PRESENCE_KEYWORD - 10)) + | (1L << (MUST_KEYWORD - 10)) + | (1L << (LIST_KEYWORD - 10)) + | (1L << (LEAF_LIST_KEYWORD - 10)) + | (1L << (LEAF_KEYWORD - 10)) + | (1L << (IF_FEATURE_KEYWORD - 10)) + | (1L << (GROUPING_KEYWORD - 10)) + | (1L << (DESCRIPTION_KEYWORD - 10)) + | (1L << (CONTAINER_KEYWORD - 10)) + | (1L << (CONFIG_KEYWORD - 10)) + | (1L << (CHOICE_KEYWORD - 10)) + | (1L << (ANYXML_KEYWORD - 10)) | (1L << (IDENTIFIER - 10)))) != 0)) { + { + setState(706); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(694); + identifier_stmt(); + } + break; + case WHEN_KEYWORD: { + setState(695); + when_stmt(); + } + break; + case IF_FEATURE_KEYWORD: { + setState(696); + if_feature_stmt(); + } + break; + case MUST_KEYWORD: { + setState(697); + must_stmt(); + } + break; + case PRESENCE_KEYWORD: { + setState(698); + presence_stmt(); + } + break; + case CONFIG_KEYWORD: { + setState(699); + config_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(700); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(701); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(702); + reference_stmt(); + } + break; + case TYPEDEF_KEYWORD: { + setState(703); + typedef_stmt(); + } + break; + case GROUPING_KEYWORD: { + setState(704); + grouping_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(705); + data_def_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(710); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(711); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Grouping_stmtContext extends ParserRuleContext { + public List grouping_stmt() { + return getRuleContexts(Grouping_stmtContext.class); + } + + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Typedef_stmtContext typedef_stmt(int i) { + return getRuleContext(Typedef_stmtContext.class, i); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Grouping_stmtContext grouping_stmt(int i) { + return getRuleContext(Grouping_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public List typedef_stmt() { + return getRuleContexts(Typedef_stmtContext.class); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public TerminalNode GROUPING_KEYWORD() { + return getToken(YangParser.GROUPING_KEYWORD, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Grouping_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_grouping_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterGrouping_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitGrouping_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitGrouping_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Grouping_stmtContext grouping_stmt() + throws RecognitionException { + Grouping_stmtContext _localctx = new Grouping_stmtContext(_ctx, + getState()); + enterRule(_localctx, 72, RULE_grouping_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(714); + match(GROUPING_KEYWORD); + setState(715); + string(); + setState(731); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(716); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(717); + match(LEFT_BRACE); + setState(727); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (USES_KEYWORD - 12)) + | (1L << (TYPEDEF_KEYWORD - 12)) + | (1L << (STATUS_KEYWORD - 12)) + | (1L << (REFERENCE_KEYWORD - 12)) + | (1L << (LIST_KEYWORD - 12)) + | (1L << (LEAF_LIST_KEYWORD - 12)) + | (1L << (LEAF_KEYWORD - 12)) + | (1L << (GROUPING_KEYWORD - 12)) + | (1L << (DESCRIPTION_KEYWORD - 12)) + | (1L << (CONTAINER_KEYWORD - 12)) + | (1L << (CHOICE_KEYWORD - 12)) + | (1L << (ANYXML_KEYWORD - 12)) | (1L << (IDENTIFIER - 12)))) != 0)) { + { + setState(725); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(718); + identifier_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(719); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(720); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(721); + reference_stmt(); + } + break; + case TYPEDEF_KEYWORD: { + setState(722); + typedef_stmt(); + } + break; + case GROUPING_KEYWORD: { + setState(723); + grouping_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(724); + data_def_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(729); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(730); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Value_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode VALUE_KEYWORD() { + return getToken(YangParser.VALUE_KEYWORD, 0); + } + + public Value_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_value_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterValue_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitValue_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitValue_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Value_stmtContext value_stmt() throws RecognitionException { + Value_stmtContext _localctx = new Value_stmtContext(_ctx, getState()); + enterRule(_localctx, 74, RULE_value_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(733); + match(VALUE_KEYWORD); + setState(734); + string(); + setState(735); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Max_value_argContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Max_value_argContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_max_value_arg; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterMax_value_arg(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitMax_value_arg(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitMax_value_arg(this); + else + return visitor.visitChildren(this); + } + } + + public final Max_value_argContext max_value_arg() + throws RecognitionException { + Max_value_argContext _localctx = new Max_value_argContext(_ctx, + getState()); + enterRule(_localctx, 76, RULE_max_value_arg); + try { + enterOuterAlt(_localctx, 1); + { + setState(737); + string(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Max_elements_stmtContext extends ParserRuleContext { + public TerminalNode MAX_ELEMENTS_KEYWORD() { + return getToken(YangParser.MAX_ELEMENTS_KEYWORD, 0); + } + + public Max_value_argContext max_value_arg() { + return getRuleContext(Max_value_argContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Max_elements_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_max_elements_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterMax_elements_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitMax_elements_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitMax_elements_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Max_elements_stmtContext max_elements_stmt() + throws RecognitionException { + Max_elements_stmtContext _localctx = new Max_elements_stmtContext(_ctx, + getState()); + enterRule(_localctx, 78, RULE_max_elements_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(739); + match(MAX_ELEMENTS_KEYWORD); + setState(740); + max_value_arg(); + setState(741); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Min_elements_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode MIN_ELEMENTS_KEYWORD() { + return getToken(YangParser.MIN_ELEMENTS_KEYWORD, 0); + } + + public Min_elements_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_min_elements_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterMin_elements_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitMin_elements_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitMin_elements_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Min_elements_stmtContext min_elements_stmt() + throws RecognitionException { + Min_elements_stmtContext _localctx = new Min_elements_stmtContext(_ctx, + getState()); + enterRule(_localctx, 80, RULE_min_elements_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(743); + match(MIN_ELEMENTS_KEYWORD); + setState(744); + string(); + setState(745); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Error_app_tag_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode ERROR_APP_TAG_KEYWORD() { + return getToken(YangParser.ERROR_APP_TAG_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Error_app_tag_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_error_app_tag_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterError_app_tag_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitError_app_tag_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitError_app_tag_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Error_app_tag_stmtContext error_app_tag_stmt() + throws RecognitionException { + Error_app_tag_stmtContext _localctx = new Error_app_tag_stmtContext( + _ctx, getState()); + enterRule(_localctx, 82, RULE_error_app_tag_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(747); + match(ERROR_APP_TAG_KEYWORD); + setState(748); + string(); + setState(749); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Error_message_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode ERROR_MESSAGE_KEYWORD() { + return getToken(YangParser.ERROR_MESSAGE_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Error_message_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_error_message_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterError_message_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitError_message_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitError_message_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Error_message_stmtContext error_message_stmt() + throws RecognitionException { + Error_message_stmtContext _localctx = new Error_message_stmtContext( + _ctx, getState()); + enterRule(_localctx, 84, RULE_error_message_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(751); + match(ERROR_MESSAGE_KEYWORD); + setState(752); + string(); + setState(753); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Must_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public List error_app_tag_stmt() { + return getRuleContexts(Error_app_tag_stmtContext.class); + } + + public TerminalNode MUST_KEYWORD() { + return getToken(YangParser.MUST_KEYWORD, 0); + } + + public Error_message_stmtContext error_message_stmt(int i) { + return getRuleContext(Error_message_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public Error_app_tag_stmtContext error_app_tag_stmt(int i) { + return getRuleContext(Error_app_tag_stmtContext.class, i); + } + + public List error_message_stmt() { + return getRuleContexts(Error_message_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Must_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_must_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterMust_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitMust_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitMust_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Must_stmtContext must_stmt() throws RecognitionException { + Must_stmtContext _localctx = new Must_stmtContext(_ctx, getState()); + enterRule(_localctx, 86, RULE_must_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(755); + match(MUST_KEYWORD); + setState(756); + string(); + setState(770); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(757); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(758); + match(LEFT_BRACE); + setState(766); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 24)) & ~0x3f) == 0 && ((1L << (_la - 24)) & ((1L << (REFERENCE_KEYWORD - 24)) + | (1L << (ERROR_MESSAGE_KEYWORD - 24)) + | (1L << (ERROR_APP_TAG_KEYWORD - 24)) + | (1L << (DESCRIPTION_KEYWORD - 24)) | (1L << (IDENTIFIER - 24)))) != 0)) { + { + setState(764); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(759); + identifier_stmt(); + } + break; + case ERROR_MESSAGE_KEYWORD: { + setState(760); + error_message_stmt(); + } + break; + case ERROR_APP_TAG_KEYWORD: { + setState(761); + error_app_tag_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(762); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(763); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(768); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(769); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Ordered_by_argContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Ordered_by_argContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_ordered_by_arg; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterOrdered_by_arg(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitOrdered_by_arg(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitOrdered_by_arg(this); + else + return visitor.visitChildren(this); + } + } + + public final Ordered_by_argContext ordered_by_arg() + throws RecognitionException { + Ordered_by_argContext _localctx = new Ordered_by_argContext(_ctx, + getState()); + enterRule(_localctx, 88, RULE_ordered_by_arg); + try { + enterOuterAlt(_localctx, 1); + { + setState(772); + string(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Ordered_by_stmtContext extends ParserRuleContext { + public Ordered_by_argContext ordered_by_arg() { + return getRuleContext(Ordered_by_argContext.class, 0); + } + + public TerminalNode ORDERED_BY_KEYWORD() { + return getToken(YangParser.ORDERED_BY_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Ordered_by_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_ordered_by_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterOrdered_by_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitOrdered_by_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitOrdered_by_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Ordered_by_stmtContext ordered_by_stmt() + throws RecognitionException { + Ordered_by_stmtContext _localctx = new Ordered_by_stmtContext(_ctx, + getState()); + enterRule(_localctx, 90, RULE_ordered_by_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(774); + match(ORDERED_BY_KEYWORD); + setState(775); + ordered_by_arg(); + setState(776); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Presence_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode PRESENCE_KEYWORD() { + return getToken(YangParser.PRESENCE_KEYWORD, 0); + } + + public Presence_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_presence_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterPresence_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitPresence_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitPresence_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Presence_stmtContext presence_stmt() + throws RecognitionException { + Presence_stmtContext _localctx = new Presence_stmtContext(_ctx, + getState()); + enterRule(_localctx, 92, RULE_presence_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(778); + match(PRESENCE_KEYWORD); + setState(779); + string(); + setState(780); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Mandatory_argContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Mandatory_argContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_mandatory_arg; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterMandatory_arg(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitMandatory_arg(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitMandatory_arg(this); + else + return visitor.visitChildren(this); + } + } + + public final Mandatory_argContext mandatory_arg() + throws RecognitionException { + Mandatory_argContext _localctx = new Mandatory_argContext(_ctx, + getState()); + enterRule(_localctx, 94, RULE_mandatory_arg); + try { + enterOuterAlt(_localctx, 1); + { + setState(782); + string(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Mandatory_stmtContext extends ParserRuleContext { + public TerminalNode MANDATORY_KEYWORD() { + return getToken(YangParser.MANDATORY_KEYWORD, 0); + } + + public Mandatory_argContext mandatory_arg() { + return getRuleContext(Mandatory_argContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Mandatory_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_mandatory_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterMandatory_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitMandatory_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitMandatory_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Mandatory_stmtContext mandatory_stmt() + throws RecognitionException { + Mandatory_stmtContext _localctx = new Mandatory_stmtContext(_ctx, + getState()); + enterRule(_localctx, 96, RULE_mandatory_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(784); + match(MANDATORY_KEYWORD); + setState(785); + mandatory_arg(); + setState(786); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Config_argContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Config_argContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_config_arg; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterConfig_arg(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitConfig_arg(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitConfig_arg(this); + else + return visitor.visitChildren(this); + } + } + + public final Config_argContext config_arg() throws RecognitionException { + Config_argContext _localctx = new Config_argContext(_ctx, getState()); + enterRule(_localctx, 98, RULE_config_arg); + try { + enterOuterAlt(_localctx, 1); + { + setState(788); + string(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Config_stmtContext extends ParserRuleContext { + public Config_argContext config_arg() { + return getRuleContext(Config_argContext.class, 0); + } + + public TerminalNode CONFIG_KEYWORD() { + return getToken(YangParser.CONFIG_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Config_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_config_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterConfig_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitConfig_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitConfig_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Config_stmtContext config_stmt() throws RecognitionException { + Config_stmtContext _localctx = new Config_stmtContext(_ctx, getState()); + enterRule(_localctx, 100, RULE_config_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(790); + match(CONFIG_KEYWORD); + setState(791); + config_arg(); + setState(792); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Status_argContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Status_argContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_status_arg; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterStatus_arg(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitStatus_arg(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitStatus_arg(this); + else + return visitor.visitChildren(this); + } + } + + public final Status_argContext status_arg() throws RecognitionException { + Status_argContext _localctx = new Status_argContext(_ctx, getState()); + enterRule(_localctx, 102, RULE_status_arg); + try { + enterOuterAlt(_localctx, 1); + { + setState(794); + string(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Status_stmtContext extends ParserRuleContext { + public Status_argContext status_arg() { + return getRuleContext(Status_argContext.class, 0); + } + + public TerminalNode STATUS_KEYWORD() { + return getToken(YangParser.STATUS_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Status_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_status_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterStatus_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitStatus_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitStatus_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Status_stmtContext status_stmt() throws RecognitionException { + Status_stmtContext _localctx = new Status_stmtContext(_ctx, getState()); + enterRule(_localctx, 104, RULE_status_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(796); + match(STATUS_KEYWORD); + setState(797); + status_arg(); + setState(798); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Position_stmtContext extends ParserRuleContext { + public TerminalNode POSITION_KEYWORD() { + return getToken(YangParser.POSITION_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Position_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_position_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterPosition_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitPosition_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitPosition_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Position_stmtContext position_stmt() + throws RecognitionException { + Position_stmtContext _localctx = new Position_stmtContext(_ctx, + getState()); + enterRule(_localctx, 106, RULE_position_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(800); + match(POSITION_KEYWORD); + setState(801); + string(); + setState(802); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Bit_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Position_stmtContext position_stmt(int i) { + return getRuleContext(Position_stmtContext.class, i); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public List position_stmt() { + return getRuleContexts(Position_stmtContext.class); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public TerminalNode BIT_KEYWORD() { + return getToken(YangParser.BIT_KEYWORD, 0); + } + + public Bit_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_bit_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterBit_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitBit_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitBit_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Bit_stmtContext bit_stmt() throws RecognitionException { + Bit_stmtContext _localctx = new Bit_stmtContext(_ctx, getState()); + enterRule(_localctx, 108, RULE_bit_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(804); + match(BIT_KEYWORD); + setState(805); + string(); + setState(819); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(806); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(807); + match(LEFT_BRACE); + setState(815); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 18)) & ~0x3f) == 0 && ((1L << (_la - 18)) & ((1L << (STATUS_KEYWORD - 18)) + | (1L << (REFERENCE_KEYWORD - 18)) + | (1L << (POSITION_KEYWORD - 18)) + | (1L << (DESCRIPTION_KEYWORD - 18)) | (1L << (IDENTIFIER - 18)))) != 0)) { + { + setState(813); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(808); + identifier_stmt(); + } + break; + case POSITION_KEYWORD: { + setState(809); + position_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(810); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(811); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(812); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(817); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(818); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Bits_specificationContext extends ParserRuleContext { + public Bit_stmtContext bit_stmt(int i) { + return getRuleContext(Bit_stmtContext.class, i); + } + + public List bit_stmt() { + return getRuleContexts(Bit_stmtContext.class); + } + + public Bits_specificationContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_bits_specification; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterBits_specification(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitBits_specification(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitBits_specification(this); + else + return visitor.visitChildren(this); + } + } + + public final Bits_specificationContext bits_specification() + throws RecognitionException { + Bits_specificationContext _localctx = new Bits_specificationContext( + _ctx, getState()); + enterRule(_localctx, 110, RULE_bits_specification); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(822); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(821); + bit_stmt(); + } + } + setState(824); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == BIT_KEYWORD); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Union_specificationContext extends ParserRuleContext { + public Type_stmtContext type_stmt(int i) { + return getRuleContext(Type_stmtContext.class, i); + } + + public List type_stmt() { + return getRuleContexts(Type_stmtContext.class); + } + + public Union_specificationContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_union_specification; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterUnion_specification(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitUnion_specification(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitUnion_specification(this); + else + return visitor.visitChildren(this); + } + } + + public final Union_specificationContext union_specification() + throws RecognitionException { + Union_specificationContext _localctx = new Union_specificationContext( + _ctx, getState()); + enterRule(_localctx, 112, RULE_union_specification); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(827); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(826); + type_stmt(); + } + } + setState(829); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == TYPE_KEYWORD); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Identityref_specificationContext extends + ParserRuleContext { + public Base_stmtContext base_stmt() { + return getRuleContext(Base_stmtContext.class, 0); + } + + public Identityref_specificationContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_identityref_specification; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterIdentityref_specification(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .exitIdentityref_specification(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitIdentityref_specification(this); + else + return visitor.visitChildren(this); + } + } + + public final Identityref_specificationContext identityref_specification() + throws RecognitionException { + Identityref_specificationContext _localctx = new Identityref_specificationContext( + _ctx, getState()); + enterRule(_localctx, 114, RULE_identityref_specification); + try { + enterOuterAlt(_localctx, 1); + { + setState(831); + base_stmt(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Instance_identifier_specificationContext extends + ParserRuleContext { + public Require_instance_stmtContext require_instance_stmt() { + return getRuleContext(Require_instance_stmtContext.class, 0); + } + + public Instance_identifier_specificationContext( + ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_instance_identifier_specification; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterInstance_identifier_specification(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .exitInstance_identifier_specification(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitInstance_identifier_specification(this); + else + return visitor.visitChildren(this); + } + } + + public final Instance_identifier_specificationContext instance_identifier_specification() + throws RecognitionException { + Instance_identifier_specificationContext _localctx = new Instance_identifier_specificationContext( + _ctx, getState()); + enterRule(_localctx, 116, RULE_instance_identifier_specification); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(834); + _la = _input.LA(1); + if (_la == REQUIRE_INSTANCE_KEYWORD) { + { + setState(833); + require_instance_stmt(); + } + } + + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Require_instance_argContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Require_instance_argContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_require_instance_arg; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRequire_instance_arg(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRequire_instance_arg(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRequire_instance_arg(this); + else + return visitor.visitChildren(this); + } + } + + public final Require_instance_argContext require_instance_arg() + throws RecognitionException { + Require_instance_argContext _localctx = new Require_instance_argContext( + _ctx, getState()); + enterRule(_localctx, 118, RULE_require_instance_arg); + try { + enterOuterAlt(_localctx, 1); + { + setState(836); + string(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Require_instance_stmtContext extends ParserRuleContext { + public Require_instance_argContext require_instance_arg() { + return getRuleContext(Require_instance_argContext.class, 0); + } + + public TerminalNode REQUIRE_INSTANCE_KEYWORD() { + return getToken(YangParser.REQUIRE_INSTANCE_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Require_instance_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_require_instance_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterRequire_instance_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRequire_instance_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRequire_instance_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Require_instance_stmtContext require_instance_stmt() + throws RecognitionException { + Require_instance_stmtContext _localctx = new Require_instance_stmtContext( + _ctx, getState()); + enterRule(_localctx, 120, RULE_require_instance_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(838); + match(REQUIRE_INSTANCE_KEYWORD); + setState(839); + require_instance_arg(); + setState(840); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Path_stmtContext extends ParserRuleContext { + public TerminalNode PATH_KEYWORD() { + return getToken(YangParser.PATH_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Path_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_path_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterPath_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitPath_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitPath_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Path_stmtContext path_stmt() throws RecognitionException { + Path_stmtContext _localctx = new Path_stmtContext(_ctx, getState()); + enterRule(_localctx, 122, RULE_path_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(842); + match(PATH_KEYWORD); + setState(843); + string(); + setState(844); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Leafref_specificationContext extends ParserRuleContext { + public Path_stmtContext path_stmt() { + return getRuleContext(Path_stmtContext.class, 0); + } + + public Leafref_specificationContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_leafref_specification; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterLeafref_specification(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitLeafref_specification(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitLeafref_specification(this); + else + return visitor.visitChildren(this); + } + } + + public final Leafref_specificationContext leafref_specification() + throws RecognitionException { + Leafref_specificationContext _localctx = new Leafref_specificationContext( + _ctx, getState()); + enterRule(_localctx, 124, RULE_leafref_specification); + try { + enterOuterAlt(_localctx, 1); + { + setState(846); + path_stmt(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Enum_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public Value_stmtContext value_stmt(int i) { + return getRuleContext(Value_stmtContext.class, i); + } + + public List value_stmt() { + return getRuleContexts(Value_stmtContext.class); + } + + public TerminalNode ENUM_KEYWORD() { + return getToken(YangParser.ENUM_KEYWORD, 0); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Enum_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_enum_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterEnum_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitEnum_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitEnum_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Enum_stmtContext enum_stmt() throws RecognitionException { + Enum_stmtContext _localctx = new Enum_stmtContext(_ctx, getState()); + enterRule(_localctx, 126, RULE_enum_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(848); + match(ENUM_KEYWORD); + setState(849); + string(); + setState(863); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(850); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(851); + match(LEFT_BRACE); + setState(859); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 11)) & ~0x3f) == 0 && ((1L << (_la - 11)) & ((1L << (VALUE_KEYWORD - 11)) + | (1L << (STATUS_KEYWORD - 11)) + | (1L << (REFERENCE_KEYWORD - 11)) + | (1L << (DESCRIPTION_KEYWORD - 11)) | (1L << (IDENTIFIER - 11)))) != 0)) { + { + setState(857); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(852); + identifier_stmt(); + } + break; + case VALUE_KEYWORD: { + setState(853); + value_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(854); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(855); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(856); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(861); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(862); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Enum_specificationContext extends ParserRuleContext { + public List enum_stmt() { + return getRuleContexts(Enum_stmtContext.class); + } + + public Enum_stmtContext enum_stmt(int i) { + return getRuleContext(Enum_stmtContext.class, i); + } + + public Enum_specificationContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_enum_specification; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterEnum_specification(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitEnum_specification(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitEnum_specification(this); + else + return visitor.visitChildren(this); + } + } + + public final Enum_specificationContext enum_specification() + throws RecognitionException { + Enum_specificationContext _localctx = new Enum_specificationContext( + _ctx, getState()); + enterRule(_localctx, 128, RULE_enum_specification); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(866); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(865); + enum_stmt(); + } + } + setState(868); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == ENUM_KEYWORD); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Default_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode DEFAULT_KEYWORD() { + return getToken(YangParser.DEFAULT_KEYWORD, 0); + } + + public Default_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_default_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterDefault_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitDefault_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitDefault_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Default_stmtContext default_stmt() throws RecognitionException { + Default_stmtContext _localctx = new Default_stmtContext(_ctx, + getState()); + enterRule(_localctx, 130, RULE_default_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(870); + match(DEFAULT_KEYWORD); + setState(871); + string(); + setState(872); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Pattern_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public List error_app_tag_stmt() { + return getRuleContexts(Error_app_tag_stmtContext.class); + } + + public Error_message_stmtContext error_message_stmt(int i) { + return getRuleContext(Error_message_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public TerminalNode PATTERN_KEYWORD() { + return getToken(YangParser.PATTERN_KEYWORD, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public Error_app_tag_stmtContext error_app_tag_stmt(int i) { + return getRuleContext(Error_app_tag_stmtContext.class, i); + } + + public List error_message_stmt() { + return getRuleContexts(Error_message_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Pattern_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_pattern_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterPattern_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitPattern_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitPattern_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Pattern_stmtContext pattern_stmt() throws RecognitionException { + Pattern_stmtContext _localctx = new Pattern_stmtContext(_ctx, + getState()); + enterRule(_localctx, 132, RULE_pattern_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(874); + match(PATTERN_KEYWORD); + setState(875); + string(); + setState(889); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(876); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(877); + match(LEFT_BRACE); + setState(885); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 24)) & ~0x3f) == 0 && ((1L << (_la - 24)) & ((1L << (REFERENCE_KEYWORD - 24)) + | (1L << (ERROR_MESSAGE_KEYWORD - 24)) + | (1L << (ERROR_APP_TAG_KEYWORD - 24)) + | (1L << (DESCRIPTION_KEYWORD - 24)) | (1L << (IDENTIFIER - 24)))) != 0)) { + { + setState(883); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(878); + identifier_stmt(); + } + break; + case ERROR_MESSAGE_KEYWORD: { + setState(879); + error_message_stmt(); + } + break; + case ERROR_APP_TAG_KEYWORD: { + setState(880); + error_app_tag_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(881); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(882); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(887); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(888); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Length_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public List error_app_tag_stmt() { + return getRuleContexts(Error_app_tag_stmtContext.class); + } + + public Error_message_stmtContext error_message_stmt(int i) { + return getRuleContext(Error_message_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public TerminalNode LENGTH_KEYWORD() { + return getToken(YangParser.LENGTH_KEYWORD, 0); + } + + public Error_app_tag_stmtContext error_app_tag_stmt(int i) { + return getRuleContext(Error_app_tag_stmtContext.class, i); + } + + public List error_message_stmt() { + return getRuleContexts(Error_message_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Length_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_length_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterLength_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitLength_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitLength_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Length_stmtContext length_stmt() throws RecognitionException { + Length_stmtContext _localctx = new Length_stmtContext(_ctx, getState()); + enterRule(_localctx, 134, RULE_length_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(891); + match(LENGTH_KEYWORD); + setState(892); + string(); + setState(906); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(893); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(894); + match(LEFT_BRACE); + setState(902); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 24)) & ~0x3f) == 0 && ((1L << (_la - 24)) & ((1L << (REFERENCE_KEYWORD - 24)) + | (1L << (ERROR_MESSAGE_KEYWORD - 24)) + | (1L << (ERROR_APP_TAG_KEYWORD - 24)) + | (1L << (DESCRIPTION_KEYWORD - 24)) | (1L << (IDENTIFIER - 24)))) != 0)) { + { + setState(900); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(895); + identifier_stmt(); + } + break; + case ERROR_MESSAGE_KEYWORD: { + setState(896); + error_message_stmt(); + } + break; + case ERROR_APP_TAG_KEYWORD: { + setState(897); + error_app_tag_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(898); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(899); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(904); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(905); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class String_restrictionsContext extends ParserRuleContext { + public Length_stmtContext length_stmt(int i) { + return getRuleContext(Length_stmtContext.class, i); + } + + public List pattern_stmt() { + return getRuleContexts(Pattern_stmtContext.class); + } + + public List length_stmt() { + return getRuleContexts(Length_stmtContext.class); + } + + public Pattern_stmtContext pattern_stmt(int i) { + return getRuleContext(Pattern_stmtContext.class, i); + } + + public String_restrictionsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_string_restrictions; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterString_restrictions(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitString_restrictions(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitString_restrictions(this); + else + return visitor.visitChildren(this); + } + } + + public final String_restrictionsContext string_restrictions() + throws RecognitionException { + String_restrictionsContext _localctx = new String_restrictionsContext( + _ctx, getState()); + enterRule(_localctx, 136, RULE_string_restrictions); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(912); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == PATTERN_KEYWORD || _la == LENGTH_KEYWORD) { + { + setState(910); + switch (_input.LA(1)) { + case LENGTH_KEYWORD: { + setState(908); + length_stmt(); + } + break; + case PATTERN_KEYWORD: { + setState(909); + pattern_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(914); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Fraction_digits_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode FRACTION_DIGITS_KEYWORD() { + return getToken(YangParser.FRACTION_DIGITS_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Fraction_digits_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_fraction_digits_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterFraction_digits_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitFraction_digits_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitFraction_digits_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Fraction_digits_stmtContext fraction_digits_stmt() + throws RecognitionException { + Fraction_digits_stmtContext _localctx = new Fraction_digits_stmtContext( + _ctx, getState()); + enterRule(_localctx, 138, RULE_fraction_digits_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(915); + match(FRACTION_DIGITS_KEYWORD); + setState(916); + string(); + setState(917); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Decimal64_specificationContext extends + ParserRuleContext { + public Fraction_digits_stmtContext fraction_digits_stmt() { + return getRuleContext(Fraction_digits_stmtContext.class, 0); + } + + public Numerical_restrictionsContext numerical_restrictions() { + return getRuleContext(Numerical_restrictionsContext.class, 0); + } + + public Decimal64_specificationContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_decimal64_specification; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterDecimal64_specification(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .exitDecimal64_specification(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitDecimal64_specification(this); + else + return visitor.visitChildren(this); + } + } + + public final Decimal64_specificationContext decimal64_specification() + throws RecognitionException { + Decimal64_specificationContext _localctx = new Decimal64_specificationContext( + _ctx, getState()); + enterRule(_localctx, 140, RULE_decimal64_specification); + int _la; + try { + setState(927); + switch (getInterpreter().adaptivePredict(_input, 101, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(920); + _la = _input.LA(1); + if (_la == RANGE_KEYWORD) { + { + setState(919); + numerical_restrictions(); + } + } + + setState(922); + fraction_digits_stmt(); + } + break; + + case 2: + enterOuterAlt(_localctx, 2); + { + setState(923); + fraction_digits_stmt(); + setState(925); + _la = _input.LA(1); + if (_la == RANGE_KEYWORD) { + { + setState(924); + numerical_restrictions(); + } + } + + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Range_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public List error_app_tag_stmt() { + return getRuleContexts(Error_app_tag_stmtContext.class); + } + + public Error_message_stmtContext error_message_stmt(int i) { + return getRuleContext(Error_message_stmtContext.class, i); + } + + public Identifier_stmtContext identifier_stmt(int i) { + return getRuleContext(Identifier_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public TerminalNode RANGE_KEYWORD() { + return getToken(YangParser.RANGE_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List identifier_stmt() { + return getRuleContexts(Identifier_stmtContext.class); + } + + public Error_app_tag_stmtContext error_app_tag_stmt(int i) { + return getRuleContext(Error_app_tag_stmtContext.class, i); + } + + public List error_message_stmt() { + return getRuleContexts(Error_message_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Range_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_range_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRange_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRange_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRange_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Range_stmtContext range_stmt() throws RecognitionException { + Range_stmtContext _localctx = new Range_stmtContext(_ctx, getState()); + enterRule(_localctx, 142, RULE_range_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(929); + match(RANGE_KEYWORD); + setState(930); + string(); + setState(944); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(931); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(932); + match(LEFT_BRACE); + setState(940); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 24)) & ~0x3f) == 0 && ((1L << (_la - 24)) & ((1L << (REFERENCE_KEYWORD - 24)) + | (1L << (ERROR_MESSAGE_KEYWORD - 24)) + | (1L << (ERROR_APP_TAG_KEYWORD - 24)) + | (1L << (DESCRIPTION_KEYWORD - 24)) | (1L << (IDENTIFIER - 24)))) != 0)) { + { + setState(938); + switch (_input.LA(1)) { + case IDENTIFIER: { + setState(933); + identifier_stmt(); + } + break; + case ERROR_MESSAGE_KEYWORD: { + setState(934); + error_message_stmt(); + } + break; + case ERROR_APP_TAG_KEYWORD: { + setState(935); + error_app_tag_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(936); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(937); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(942); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(943); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Numerical_restrictionsContext extends ParserRuleContext { + public Range_stmtContext range_stmt() { + return getRuleContext(Range_stmtContext.class, 0); + } + + public Numerical_restrictionsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_numerical_restrictions; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterNumerical_restrictions(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .exitNumerical_restrictions(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitNumerical_restrictions(this); + else + return visitor.visitChildren(this); + } + } + + public final Numerical_restrictionsContext numerical_restrictions() + throws RecognitionException { + Numerical_restrictionsContext _localctx = new Numerical_restrictionsContext( + _ctx, getState()); + enterRule(_localctx, 144, RULE_numerical_restrictions); + try { + enterOuterAlt(_localctx, 1); + { + setState(946); + range_stmt(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Type_body_stmtsContext extends ParserRuleContext { + public Bits_specificationContext bits_specification() { + return getRuleContext(Bits_specificationContext.class, 0); + } + + public Identityref_specificationContext identityref_specification() { + return getRuleContext(Identityref_specificationContext.class, 0); + } + + public Enum_specificationContext enum_specification() { + return getRuleContext(Enum_specificationContext.class, 0); + } + + public Numerical_restrictionsContext numerical_restrictions() { + return getRuleContext(Numerical_restrictionsContext.class, 0); + } + + public String_restrictionsContext string_restrictions() { + return getRuleContext(String_restrictionsContext.class, 0); + } + + public Leafref_specificationContext leafref_specification() { + return getRuleContext(Leafref_specificationContext.class, 0); + } + + public Decimal64_specificationContext decimal64_specification() { + return getRuleContext(Decimal64_specificationContext.class, 0); + } + + public Union_specificationContext union_specification() { + return getRuleContext(Union_specificationContext.class, 0); + } + + public Instance_identifier_specificationContext instance_identifier_specification() { + return getRuleContext( + Instance_identifier_specificationContext.class, 0); + } + + public Type_body_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_type_body_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterType_body_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitType_body_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitType_body_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Type_body_stmtsContext type_body_stmts() + throws RecognitionException { + Type_body_stmtsContext _localctx = new Type_body_stmtsContext(_ctx, + getState()); + enterRule(_localctx, 146, RULE_type_body_stmts); + try { + setState(957); + switch (getInterpreter().adaptivePredict(_input, 105, _ctx)) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(948); + numerical_restrictions(); + } + break; + + case 2: + enterOuterAlt(_localctx, 2); + { + setState(949); + decimal64_specification(); + } + break; + + case 3: + enterOuterAlt(_localctx, 3); + { + setState(950); + string_restrictions(); + } + break; + + case 4: + enterOuterAlt(_localctx, 4); + { + setState(951); + enum_specification(); + } + break; + + case 5: + enterOuterAlt(_localctx, 5); + { + setState(952); + leafref_specification(); + } + break; + + case 6: + enterOuterAlt(_localctx, 6); + { + setState(953); + identityref_specification(); + } + break; + + case 7: + enterOuterAlt(_localctx, 7); + { + setState(954); + instance_identifier_specification(); + } + break; + + case 8: + enterOuterAlt(_localctx, 8); + { + setState(955); + bits_specification(); + } + break; + + case 9: + enterOuterAlt(_localctx, 9); + { + setState(956); + union_specification(); + } + break; + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Type_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public TerminalNode TYPE_KEYWORD() { + return getToken(YangParser.TYPE_KEYWORD, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Type_body_stmtsContext type_body_stmts() { + return getRuleContext(Type_body_stmtsContext.class, 0); + } + + public Type_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_type_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterType_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitType_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitType_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Type_stmtContext type_stmt() throws RecognitionException { + Type_stmtContext _localctx = new Type_stmtContext(_ctx, getState()); + enterRule(_localctx, 148, RULE_type_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(959); + match(TYPE_KEYWORD); + setState(960); + string(); + setState(966); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(961); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(962); + match(LEFT_BRACE); + setState(963); + type_body_stmts(); + setState(964); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Typedef_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Units_stmtContext units_stmt(int i) { + return getRuleContext(Units_stmtContext.class, i); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Default_stmtContext default_stmt(int i) { + return getRuleContext(Default_stmtContext.class, i); + } + + public List units_stmt() { + return getRuleContexts(Units_stmtContext.class); + } + + public Type_stmtContext type_stmt(int i) { + return getRuleContext(Type_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List type_stmt() { + return getRuleContexts(Type_stmtContext.class); + } + + public TerminalNode TYPEDEF_KEYWORD() { + return getToken(YangParser.TYPEDEF_KEYWORD, 0); + } + + public List default_stmt() { + return getRuleContexts(Default_stmtContext.class); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Typedef_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_typedef_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterTypedef_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitTypedef_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitTypedef_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Typedef_stmtContext typedef_stmt() throws RecognitionException { + Typedef_stmtContext _localctx = new Typedef_stmtContext(_ctx, + getState()); + enterRule(_localctx, 150, RULE_typedef_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(968); + match(TYPEDEF_KEYWORD); + setState(969); + string(); + setState(970); + match(LEFT_BRACE); + setState(977); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(977); + switch (_input.LA(1)) { + case TYPE_KEYWORD: { + setState(971); + type_stmt(); + } + break; + case UNITS_KEYWORD: { + setState(972); + units_stmt(); + } + break; + case DEFAULT_KEYWORD: { + setState(973); + default_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(974); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(975); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(976); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(979); + _errHandler.sync(this); + _la = _input.LA(1); + } while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << UNITS_KEYWORD) + | (1L << TYPE_KEYWORD) + | (1L << STATUS_KEYWORD) + | (1L << REFERENCE_KEYWORD) + | (1L << DESCRIPTION_KEYWORD) | (1L << DEFAULT_KEYWORD))) != 0)); + setState(981); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class If_feature_stmtContext extends ParserRuleContext { + public TerminalNode IF_FEATURE_KEYWORD() { + return getToken(YangParser.IF_FEATURE_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public If_feature_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_if_feature_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterIf_feature_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitIf_feature_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitIf_feature_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final If_feature_stmtContext if_feature_stmt() + throws RecognitionException { + If_feature_stmtContext _localctx = new If_feature_stmtContext(_ctx, + getState()); + enterRule(_localctx, 152, RULE_if_feature_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(983); + match(IF_FEATURE_KEYWORD); + setState(984); + string(); + setState(985); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Feature_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public If_feature_stmtContext if_feature_stmt(int i) { + return getRuleContext(If_feature_stmtContext.class, i); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public List if_feature_stmt() { + return getRuleContexts(If_feature_stmtContext.class); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode FEATURE_KEYWORD() { + return getToken(YangParser.FEATURE_KEYWORD, 0); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Feature_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_feature_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterFeature_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitFeature_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitFeature_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Feature_stmtContext feature_stmt() throws RecognitionException { + Feature_stmtContext _localctx = new Feature_stmtContext(_ctx, + getState()); + enterRule(_localctx, 154, RULE_feature_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(987); + match(FEATURE_KEYWORD); + setState(988); + string(); + setState(1001); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(989); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(990); + match(LEFT_BRACE); + setState(997); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << STATUS_KEYWORD) + | (1L << REFERENCE_KEYWORD) + | (1L << IF_FEATURE_KEYWORD) | (1L << DESCRIPTION_KEYWORD))) != 0)) { + { + setState(995); + switch (_input.LA(1)) { + case IF_FEATURE_KEYWORD: { + setState(991); + if_feature_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(992); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(993); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(994); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(999); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1000); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Base_stmtContext extends ParserRuleContext { + public TerminalNode BASE_KEYWORD() { + return getToken(YangParser.BASE_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Base_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_base_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterBase_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitBase_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitBase_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Base_stmtContext base_stmt() throws RecognitionException { + Base_stmtContext _localctx = new Base_stmtContext(_ctx, getState()); + enterRule(_localctx, 156, RULE_base_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1003); + match(BASE_KEYWORD); + setState(1004); + string(); + setState(1005); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Identity_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Base_stmtContext base_stmt(int i) { + return getRuleContext(Base_stmtContext.class, i); + } + + public TerminalNode IDENTITY_KEYWORD() { + return getToken(YangParser.IDENTITY_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List base_stmt() { + return getRuleContexts(Base_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Identity_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_identity_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterIdentity_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitIdentity_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitIdentity_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Identity_stmtContext identity_stmt() + throws RecognitionException { + Identity_stmtContext _localctx = new Identity_stmtContext(_ctx, + getState()); + enterRule(_localctx, 158, RULE_identity_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1007); + match(IDENTITY_KEYWORD); + setState(1008); + string(); + setState(1021); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(1009); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(1010); + match(LEFT_BRACE); + setState(1017); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 18)) & ~0x3f) == 0 && ((1L << (_la - 18)) & ((1L << (STATUS_KEYWORD - 18)) + | (1L << (REFERENCE_KEYWORD - 18)) + | (1L << (DESCRIPTION_KEYWORD - 18)) | (1L << (BASE_KEYWORD - 18)))) != 0)) { + { + setState(1015); + switch (_input.LA(1)) { + case BASE_KEYWORD: { + setState(1011); + base_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(1012); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(1013); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(1014); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(1019); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1020); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Yin_element_argContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Yin_element_argContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_yin_element_arg; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterYin_element_arg(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitYin_element_arg(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitYin_element_arg(this); + else + return visitor.visitChildren(this); + } + } + + public final Yin_element_argContext yin_element_arg() + throws RecognitionException { + Yin_element_argContext _localctx = new Yin_element_argContext(_ctx, + getState()); + enterRule(_localctx, 160, RULE_yin_element_arg); + try { + enterOuterAlt(_localctx, 1); + { + setState(1023); + string(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Yin_element_stmtContext extends ParserRuleContext { + public TerminalNode YIN_ELEMENT_KEYWORD() { + return getToken(YangParser.YIN_ELEMENT_KEYWORD, 0); + } + + public Yin_element_argContext yin_element_arg() { + return getRuleContext(Yin_element_argContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Yin_element_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_yin_element_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterYin_element_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitYin_element_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitYin_element_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Yin_element_stmtContext yin_element_stmt() + throws RecognitionException { + Yin_element_stmtContext _localctx = new Yin_element_stmtContext(_ctx, + getState()); + enterRule(_localctx, 162, RULE_yin_element_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1025); + match(YIN_ELEMENT_KEYWORD); + setState(1026); + yin_element_arg(); + setState(1027); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Argument_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Yin_element_stmtContext yin_element_stmt() { + return getRuleContext(Yin_element_stmtContext.class, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public TerminalNode ARGUMENT_KEYWORD() { + return getToken(YangParser.ARGUMENT_KEYWORD, 0); + } + + public Argument_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_argument_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterArgument_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitArgument_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitArgument_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Argument_stmtContext argument_stmt() + throws RecognitionException { + Argument_stmtContext _localctx = new Argument_stmtContext(_ctx, + getState()); + enterRule(_localctx, 164, RULE_argument_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1029); + match(ARGUMENT_KEYWORD); + setState(1030); + string(); + setState(1037); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(1031); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(1032); + match(LEFT_BRACE); + setState(1034); + _la = _input.LA(1); + if (_la == YIN_ELEMENT_KEYWORD) { + { + setState(1033); + yin_element_stmt(); + } + } + + setState(1036); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Extension_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public TerminalNode EXTENSION_KEYWORD() { + return getToken(YangParser.EXTENSION_KEYWORD, 0); + } + + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public List argument_stmt() { + return getRuleContexts(Argument_stmtContext.class); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Status_stmtContext status_stmt(int i) { + return getRuleContext(Status_stmtContext.class, i); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public List status_stmt() { + return getRuleContexts(Status_stmtContext.class); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Argument_stmtContext argument_stmt(int i) { + return getRuleContext(Argument_stmtContext.class, i); + } + + public Extension_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_extension_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterExtension_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitExtension_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitExtension_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Extension_stmtContext extension_stmt() + throws RecognitionException { + Extension_stmtContext _localctx = new Extension_stmtContext(_ctx, + getState()); + enterRule(_localctx, 166, RULE_extension_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1039); + match(EXTENSION_KEYWORD); + setState(1040); + string(); + setState(1053); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(1041); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(1042); + match(LEFT_BRACE); + setState(1049); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 18)) & ~0x3f) == 0 && ((1L << (_la - 18)) & ((1L << (STATUS_KEYWORD - 18)) + | (1L << (REFERENCE_KEYWORD - 18)) + | (1L << (DESCRIPTION_KEYWORD - 18)) | (1L << (ARGUMENT_KEYWORD - 18)))) != 0)) { + { + setState(1047); + switch (_input.LA(1)) { + case ARGUMENT_KEYWORD: { + setState(1043); + argument_stmt(); + } + break; + case STATUS_KEYWORD: { + setState(1044); + status_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(1045); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(1046); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(1051); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1052); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Revision_date_stmtContext extends ParserRuleContext { + public TerminalNode REVISION_DATE_KEYWORD() { + return getToken(YangParser.REVISION_DATE_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Revision_date_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_revision_date_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRevision_date_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRevision_date_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRevision_date_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Revision_date_stmtContext revision_date_stmt() + throws RecognitionException { + Revision_date_stmtContext _localctx = new Revision_date_stmtContext( + _ctx, getState()); + enterRule(_localctx, 168, RULE_revision_date_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1055); + match(REVISION_DATE_KEYWORD); + setState(1056); + string(); + setState(1057); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Revision_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Reference_stmtContext reference_stmt() { + return getRuleContext(Reference_stmtContext.class, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public TerminalNode REVISION_KEYWORD() { + return getToken(YangParser.REVISION_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Description_stmtContext description_stmt() { + return getRuleContext(Description_stmtContext.class, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Revision_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_revision_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRevision_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRevision_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRevision_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Revision_stmtContext revision_stmt() + throws RecognitionException { + Revision_stmtContext _localctx = new Revision_stmtContext(_ctx, + getState()); + enterRule(_localctx, 170, RULE_revision_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1059); + match(REVISION_KEYWORD); + setState(1060); + string(); + setState(1070); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(1061); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(1062); + match(LEFT_BRACE); + setState(1064); + _la = _input.LA(1); + if (_la == DESCRIPTION_KEYWORD) { + { + setState(1063); + description_stmt(); + } + } + + setState(1067); + _la = _input.LA(1); + if (_la == REFERENCE_KEYWORD) { + { + setState(1066); + reference_stmt(); + } + } + + setState(1069); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Units_stmtContext extends ParserRuleContext { + public TerminalNode UNITS_KEYWORD() { + return getToken(YangParser.UNITS_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Units_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_units_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterUnits_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitUnits_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitUnits_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Units_stmtContext units_stmt() throws RecognitionException { + Units_stmtContext _localctx = new Units_stmtContext(_ctx, getState()); + enterRule(_localctx, 172, RULE_units_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1072); + match(UNITS_KEYWORD); + setState(1073); + string(); + setState(1074); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Reference_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode REFERENCE_KEYWORD() { + return getToken(YangParser.REFERENCE_KEYWORD, 0); + } + + public Reference_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_reference_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterReference_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitReference_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitReference_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Reference_stmtContext reference_stmt() + throws RecognitionException { + Reference_stmtContext _localctx = new Reference_stmtContext(_ctx, + getState()); + enterRule(_localctx, 174, RULE_reference_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1076); + match(REFERENCE_KEYWORD); + setState(1077); + string(); + setState(1078); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Description_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode DESCRIPTION_KEYWORD() { + return getToken(YangParser.DESCRIPTION_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Description_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_description_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterDescription_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitDescription_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitDescription_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Description_stmtContext description_stmt() + throws RecognitionException { + Description_stmtContext _localctx = new Description_stmtContext(_ctx, + getState()); + enterRule(_localctx, 176, RULE_description_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1080); + match(DESCRIPTION_KEYWORD); + setState(1081); + string(); + setState(1082); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Contact_stmtContext extends ParserRuleContext { + public TerminalNode CONTACT_KEYWORD() { + return getToken(YangParser.CONTACT_KEYWORD, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Contact_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_contact_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterContact_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitContact_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitContact_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Contact_stmtContext contact_stmt() throws RecognitionException { + Contact_stmtContext _localctx = new Contact_stmtContext(_ctx, + getState()); + enterRule(_localctx, 178, RULE_contact_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1084); + match(CONTACT_KEYWORD); + setState(1085); + string(); + setState(1086); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Organization_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode ORGANIZATION_KEYWORD() { + return getToken(YangParser.ORGANIZATION_KEYWORD, 0); + } + + public Organization_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_organization_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterOrganization_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitOrganization_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitOrganization_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Organization_stmtContext organization_stmt() + throws RecognitionException { + Organization_stmtContext _localctx = new Organization_stmtContext(_ctx, + getState()); + enterRule(_localctx, 180, RULE_organization_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1088); + match(ORGANIZATION_KEYWORD); + setState(1089); + string(); + setState(1090); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Belongs_to_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode BELONGS_TO_KEYWORD() { + return getToken(YangParser.BELONGS_TO_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Prefix_stmtContext prefix_stmt() { + return getRuleContext(Prefix_stmtContext.class, 0); + } + + public Belongs_to_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_belongs_to_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterBelongs_to_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitBelongs_to_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitBelongs_to_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Belongs_to_stmtContext belongs_to_stmt() + throws RecognitionException { + Belongs_to_stmtContext _localctx = new Belongs_to_stmtContext(_ctx, + getState()); + enterRule(_localctx, 182, RULE_belongs_to_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1092); + match(BELONGS_TO_KEYWORD); + setState(1093); + string(); + setState(1094); + match(LEFT_BRACE); + setState(1095); + prefix_stmt(); + setState(1096); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Prefix_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode PREFIX_KEYWORD() { + return getToken(YangParser.PREFIX_KEYWORD, 0); + } + + public Prefix_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_prefix_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterPrefix_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitPrefix_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitPrefix_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Prefix_stmtContext prefix_stmt() throws RecognitionException { + Prefix_stmtContext _localctx = new Prefix_stmtContext(_ctx, getState()); + enterRule(_localctx, 184, RULE_prefix_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1098); + match(PREFIX_KEYWORD); + setState(1099); + string(); + setState(1100); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Namespace_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode NAMESPACE_KEYWORD() { + return getToken(YangParser.NAMESPACE_KEYWORD, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public Namespace_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_namespace_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterNamespace_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitNamespace_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitNamespace_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Namespace_stmtContext namespace_stmt() + throws RecognitionException { + Namespace_stmtContext _localctx = new Namespace_stmtContext(_ctx, + getState()); + enterRule(_localctx, 186, RULE_namespace_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1102); + match(NAMESPACE_KEYWORD); + setState(1103); + string(); + setState(1104); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Include_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public TerminalNode SEMICOLON() { + return getToken(YangParser.SEMICOLON, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode INCLUDE_KEYWORD() { + return getToken(YangParser.INCLUDE_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Revision_date_stmtContext revision_date_stmt() { + return getRuleContext(Revision_date_stmtContext.class, 0); + } + + public Include_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_include_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterInclude_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitInclude_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitInclude_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Include_stmtContext include_stmt() throws RecognitionException { + Include_stmtContext _localctx = new Include_stmtContext(_ctx, + getState()); + enterRule(_localctx, 188, RULE_include_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1106); + match(INCLUDE_KEYWORD); + setState(1107); + string(); + setState(1114); + switch (_input.LA(1)) { + case SEMICOLON: { + setState(1108); + match(SEMICOLON); + } + break; + case LEFT_BRACE: { + { + setState(1109); + match(LEFT_BRACE); + setState(1111); + _la = _input.LA(1); + if (_la == REVISION_DATE_KEYWORD) { + { + setState(1110); + revision_date_stmt(); + } + } + + setState(1113); + match(RIGHT_BRACE); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Import_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Prefix_stmtContext prefix_stmt() { + return getRuleContext(Prefix_stmtContext.class, 0); + } + + public Revision_date_stmtContext revision_date_stmt() { + return getRuleContext(Revision_date_stmtContext.class, 0); + } + + public TerminalNode IMPORT_KEYWORD() { + return getToken(YangParser.IMPORT_KEYWORD, 0); + } + + public Import_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_import_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterImport_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitImport_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitImport_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Import_stmtContext import_stmt() throws RecognitionException { + Import_stmtContext _localctx = new Import_stmtContext(_ctx, getState()); + enterRule(_localctx, 190, RULE_import_stmt); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1116); + match(IMPORT_KEYWORD); + setState(1117); + string(); + setState(1118); + match(LEFT_BRACE); + setState(1119); + prefix_stmt(); + setState(1121); + _la = _input.LA(1); + if (_la == REVISION_DATE_KEYWORD) { + { + setState(1120); + revision_date_stmt(); + } + } + + setState(1123); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Yang_version_stmtContext extends ParserRuleContext { + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public StmtendContext stmtend() { + return getRuleContext(StmtendContext.class, 0); + } + + public TerminalNode YANG_VERSION_KEYWORD() { + return getToken(YangParser.YANG_VERSION_KEYWORD, 0); + } + + public Yang_version_stmtContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_yang_version_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterYang_version_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitYang_version_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitYang_version_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Yang_version_stmtContext yang_version_stmt() + throws RecognitionException { + Yang_version_stmtContext _localctx = new Yang_version_stmtContext(_ctx, + getState()); + enterRule(_localctx, 192, RULE_yang_version_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1125); + match(YANG_VERSION_KEYWORD); + setState(1126); + string(); + setState(1127); + stmtend(); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Data_def_stmtContext extends ParserRuleContext { + public Uses_stmtContext uses_stmt() { + return getRuleContext(Uses_stmtContext.class, 0); + } + + public Anyxml_stmtContext anyxml_stmt() { + return getRuleContext(Anyxml_stmtContext.class, 0); + } + + public List_stmtContext list_stmt() { + return getRuleContext(List_stmtContext.class, 0); + } + + public Leaf_stmtContext leaf_stmt() { + return getRuleContext(Leaf_stmtContext.class, 0); + } + + public Container_stmtContext container_stmt() { + return getRuleContext(Container_stmtContext.class, 0); + } + + public Choice_stmtContext choice_stmt() { + return getRuleContext(Choice_stmtContext.class, 0); + } + + public Leaf_list_stmtContext leaf_list_stmt() { + return getRuleContext(Leaf_list_stmtContext.class, 0); + } + + public Data_def_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_data_def_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterData_def_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitData_def_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitData_def_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Data_def_stmtContext data_def_stmt() + throws RecognitionException { + Data_def_stmtContext _localctx = new Data_def_stmtContext(_ctx, + getState()); + enterRule(_localctx, 194, RULE_data_def_stmt); + try { + setState(1136); + switch (_input.LA(1)) { + case CONTAINER_KEYWORD: + enterOuterAlt(_localctx, 1); + { + setState(1129); + container_stmt(); + } + break; + case LEAF_KEYWORD: + enterOuterAlt(_localctx, 2); + { + setState(1130); + leaf_stmt(); + } + break; + case LEAF_LIST_KEYWORD: + enterOuterAlt(_localctx, 3); + { + setState(1131); + leaf_list_stmt(); + } + break; + case LIST_KEYWORD: + enterOuterAlt(_localctx, 4); + { + setState(1132); + list_stmt(); + } + break; + case CHOICE_KEYWORD: + enterOuterAlt(_localctx, 5); + { + setState(1133); + choice_stmt(); + } + break; + case ANYXML_KEYWORD: + enterOuterAlt(_localctx, 6); + { + setState(1134); + anyxml_stmt(); + } + break; + case USES_KEYWORD: + enterOuterAlt(_localctx, 7); + { + setState(1135); + uses_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Body_stmtsContext extends ParserRuleContext { + public List grouping_stmt() { + return getRuleContexts(Grouping_stmtContext.class); + } + + public List feature_stmt() { + return getRuleContexts(Feature_stmtContext.class); + } + + public Identity_stmtContext identity_stmt(int i) { + return getRuleContext(Identity_stmtContext.class, i); + } + + public Typedef_stmtContext typedef_stmt(int i) { + return getRuleContext(Typedef_stmtContext.class, i); + } + + public List notification_stmt() { + return getRuleContexts(Notification_stmtContext.class); + } + + public Grouping_stmtContext grouping_stmt(int i) { + return getRuleContext(Grouping_stmtContext.class, i); + } + + public Deviation_stmtContext deviation_stmt(int i) { + return getRuleContext(Deviation_stmtContext.class, i); + } + + public Rpc_stmtContext rpc_stmt(int i) { + return getRuleContext(Rpc_stmtContext.class, i); + } + + public Feature_stmtContext feature_stmt(int i) { + return getRuleContext(Feature_stmtContext.class, i); + } + + public List augment_stmt() { + return getRuleContexts(Augment_stmtContext.class); + } + + public List rpc_stmt() { + return getRuleContexts(Rpc_stmtContext.class); + } + + public List typedef_stmt() { + return getRuleContexts(Typedef_stmtContext.class); + } + + public Data_def_stmtContext data_def_stmt(int i) { + return getRuleContext(Data_def_stmtContext.class, i); + } + + public List extension_stmt() { + return getRuleContexts(Extension_stmtContext.class); + } + + public Extension_stmtContext extension_stmt(int i) { + return getRuleContext(Extension_stmtContext.class, i); + } + + public List data_def_stmt() { + return getRuleContexts(Data_def_stmtContext.class); + } + + public List identity_stmt() { + return getRuleContexts(Identity_stmtContext.class); + } + + public List deviation_stmt() { + return getRuleContexts(Deviation_stmtContext.class); + } + + public Augment_stmtContext augment_stmt(int i) { + return getRuleContext(Augment_stmtContext.class, i); + } + + public Notification_stmtContext notification_stmt(int i) { + return getRuleContext(Notification_stmtContext.class, i); + } + + public Body_stmtsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_body_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterBody_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitBody_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitBody_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Body_stmtsContext body_stmts() throws RecognitionException { + Body_stmtsContext _localctx = new Body_stmtsContext(_ctx, getState()); + enterRule(_localctx, 196, RULE_body_stmts); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1152); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (USES_KEYWORD - 12)) + | (1L << (TYPEDEF_KEYWORD - 12)) + | (1L << (RPC_KEYWORD - 12)) + | (1L << (NOTIFICATION_KEYWORD - 12)) + | (1L << (LIST_KEYWORD - 12)) + | (1L << (LEAF_LIST_KEYWORD - 12)) + | (1L << (LEAF_KEYWORD - 12)) + | (1L << (IDENTITY_KEYWORD - 12)) + | (1L << (GROUPING_KEYWORD - 12)) + | (1L << (FEATURE_KEYWORD - 12)) + | (1L << (DEVIATION_KEYWORD - 12)) + | (1L << (EXTENSION_KEYWORD - 12)) + | (1L << (CONTAINER_KEYWORD - 12)) + | (1L << (CHOICE_KEYWORD - 12)) + | (1L << (AUGMENT_KEYWORD - 12)) | (1L << (ANYXML_KEYWORD - 12)))) != 0)) { + { + { + setState(1148); + switch (_input.LA(1)) { + case EXTENSION_KEYWORD: { + setState(1138); + extension_stmt(); + } + break; + case FEATURE_KEYWORD: { + setState(1139); + feature_stmt(); + } + break; + case IDENTITY_KEYWORD: { + setState(1140); + identity_stmt(); + } + break; + case TYPEDEF_KEYWORD: { + setState(1141); + typedef_stmt(); + } + break; + case GROUPING_KEYWORD: { + setState(1142); + grouping_stmt(); + } + break; + case USES_KEYWORD: + case LIST_KEYWORD: + case LEAF_LIST_KEYWORD: + case LEAF_KEYWORD: + case CONTAINER_KEYWORD: + case CHOICE_KEYWORD: + case ANYXML_KEYWORD: { + setState(1143); + data_def_stmt(); + } + break; + case AUGMENT_KEYWORD: { + setState(1144); + augment_stmt(); + } + break; + case RPC_KEYWORD: { + setState(1145); + rpc_stmt(); + } + break; + case NOTIFICATION_KEYWORD: { + setState(1146); + notification_stmt(); + } + break; + case DEVIATION_KEYWORD: { + setState(1147); + deviation_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + setState(1154); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Revision_stmtsContext extends ParserRuleContext { + public List revision_stmt() { + return getRuleContexts(Revision_stmtContext.class); + } + + public Revision_stmtContext revision_stmt(int i) { + return getRuleContext(Revision_stmtContext.class, i); + } + + public Revision_stmtsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_revision_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterRevision_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitRevision_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitRevision_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Revision_stmtsContext revision_stmts() + throws RecognitionException { + Revision_stmtsContext _localctx = new Revision_stmtsContext(_ctx, + getState()); + enterRule(_localctx, 198, RULE_revision_stmts); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1158); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == REVISION_KEYWORD) { + { + { + setState(1155); + revision_stmt(); + } + } + setState(1160); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Linkage_stmtsContext extends ParserRuleContext { + public List include_stmt() { + return getRuleContexts(Include_stmtContext.class); + } + + public Import_stmtContext import_stmt(int i) { + return getRuleContext(Import_stmtContext.class, i); + } + + public Include_stmtContext include_stmt(int i) { + return getRuleContext(Include_stmtContext.class, i); + } + + public List import_stmt() { + return getRuleContexts(Import_stmtContext.class); + } + + public Linkage_stmtsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_linkage_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterLinkage_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitLinkage_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitLinkage_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Linkage_stmtsContext linkage_stmts() + throws RecognitionException { + Linkage_stmtsContext _localctx = new Linkage_stmtsContext(_ctx, + getState()); + enterRule(_localctx, 200, RULE_linkage_stmts); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1165); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == INCLUDE_KEYWORD || _la == IMPORT_KEYWORD) { + { + setState(1163); + switch (_input.LA(1)) { + case IMPORT_KEYWORD: { + setState(1161); + import_stmt(); + } + break; + case INCLUDE_KEYWORD: { + setState(1162); + include_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(1167); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Meta_stmtsContext extends ParserRuleContext { + public List reference_stmt() { + return getRuleContexts(Reference_stmtContext.class); + } + + public Description_stmtContext description_stmt(int i) { + return getRuleContext(Description_stmtContext.class, i); + } + + public Organization_stmtContext organization_stmt(int i) { + return getRuleContext(Organization_stmtContext.class, i); + } + + public Contact_stmtContext contact_stmt(int i) { + return getRuleContext(Contact_stmtContext.class, i); + } + + public List contact_stmt() { + return getRuleContexts(Contact_stmtContext.class); + } + + public List organization_stmt() { + return getRuleContexts(Organization_stmtContext.class); + } + + public List description_stmt() { + return getRuleContexts(Description_stmtContext.class); + } + + public Reference_stmtContext reference_stmt(int i) { + return getRuleContext(Reference_stmtContext.class, i); + } + + public Meta_stmtsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_meta_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterMeta_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitMeta_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitMeta_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Meta_stmtsContext meta_stmts() throws RecognitionException { + Meta_stmtsContext _localctx = new Meta_stmtsContext(_ctx, getState()); + enterRule(_localctx, 202, RULE_meta_stmts); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1174); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << REFERENCE_KEYWORD) + | (1L << ORGANIZATION_KEYWORD) + | (1L << DESCRIPTION_KEYWORD) | (1L << CONTACT_KEYWORD))) != 0)) { + { + setState(1172); + switch (_input.LA(1)) { + case ORGANIZATION_KEYWORD: { + setState(1168); + organization_stmt(); + } + break; + case CONTACT_KEYWORD: { + setState(1169); + contact_stmt(); + } + break; + case DESCRIPTION_KEYWORD: { + setState(1170); + description_stmt(); + } + break; + case REFERENCE_KEYWORD: { + setState(1171); + reference_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(1176); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Submodule_header_stmtsContext extends ParserRuleContext { + public Belongs_to_stmtContext belongs_to_stmt(int i) { + return getRuleContext(Belongs_to_stmtContext.class, i); + } + + public List belongs_to_stmt() { + return getRuleContexts(Belongs_to_stmtContext.class); + } + + public Yang_version_stmtContext yang_version_stmt(int i) { + return getRuleContext(Yang_version_stmtContext.class, i); + } + + public List yang_version_stmt() { + return getRuleContexts(Yang_version_stmtContext.class); + } + + public Submodule_header_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_submodule_header_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .enterSubmodule_header_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener) + .exitSubmodule_header_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitSubmodule_header_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Submodule_header_stmtsContext submodule_header_stmts() + throws RecognitionException { + Submodule_header_stmtsContext _localctx = new Submodule_header_stmtsContext( + _ctx, getState()); + enterRule(_localctx, 204, RULE_submodule_header_stmts); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1179); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(1179); + switch (_input.LA(1)) { + case YANG_VERSION_KEYWORD: { + setState(1177); + yang_version_stmt(); + } + break; + case BELONGS_TO_KEYWORD: { + setState(1178); + belongs_to_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(1181); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == YANG_VERSION_KEYWORD + || _la == BELONGS_TO_KEYWORD); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Module_header_stmtsContext extends ParserRuleContext { + public List namespace_stmt() { + return getRuleContexts(Namespace_stmtContext.class); + } + + public Namespace_stmtContext namespace_stmt(int i) { + return getRuleContext(Namespace_stmtContext.class, i); + } + + public Yang_version_stmtContext yang_version_stmt(int i) { + return getRuleContext(Yang_version_stmtContext.class, i); + } + + public Prefix_stmtContext prefix_stmt(int i) { + return getRuleContext(Prefix_stmtContext.class, i); + } + + public List prefix_stmt() { + return getRuleContexts(Prefix_stmtContext.class); + } + + public List yang_version_stmt() { + return getRuleContexts(Yang_version_stmtContext.class); + } + + public Module_header_stmtsContext(ParserRuleContext parent, + int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_module_header_stmts; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterModule_header_stmts(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitModule_header_stmts(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitModule_header_stmts(this); + else + return visitor.visitChildren(this); + } + } + + public final Module_header_stmtsContext module_header_stmts() + throws RecognitionException { + Module_header_stmtsContext _localctx = new Module_header_stmtsContext( + _ctx, getState()); + enterRule(_localctx, 206, RULE_module_header_stmts); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1186); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(1186); + switch (_input.LA(1)) { + case YANG_VERSION_KEYWORD: { + setState(1183); + yang_version_stmt(); + } + break; + case NAMESPACE_KEYWORD: { + setState(1184); + namespace_stmt(); + } + break; + case PREFIX_KEYWORD: { + setState(1185); + prefix_stmt(); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(1188); + _errHandler.sync(this); + _la = _input.LA(1); + } while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << YANG_VERSION_KEYWORD) + | (1L << PREFIX_KEYWORD) | (1L << NAMESPACE_KEYWORD))) != 0)); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Submodule_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Linkage_stmtsContext linkage_stmts() { + return getRuleContext(Linkage_stmtsContext.class, 0); + } + + public Revision_stmtsContext revision_stmts() { + return getRuleContext(Revision_stmtsContext.class, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Body_stmtsContext body_stmts() { + return getRuleContext(Body_stmtsContext.class, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public TerminalNode SUBMODULE_KEYWORD() { + return getToken(YangParser.SUBMODULE_KEYWORD, 0); + } + + public Submodule_header_stmtsContext submodule_header_stmts() { + return getRuleContext(Submodule_header_stmtsContext.class, 0); + } + + public Meta_stmtsContext meta_stmts() { + return getRuleContext(Meta_stmtsContext.class, 0); + } + + public Submodule_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_submodule_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterSubmodule_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitSubmodule_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitSubmodule_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Submodule_stmtContext submodule_stmt() + throws RecognitionException { + Submodule_stmtContext _localctx = new Submodule_stmtContext(_ctx, + getState()); + enterRule(_localctx, 208, RULE_submodule_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1190); + match(SUBMODULE_KEYWORD); + setState(1191); + string(); + setState(1192); + match(LEFT_BRACE); + setState(1193); + submodule_header_stmts(); + setState(1194); + linkage_stmts(); + setState(1195); + meta_stmts(); + setState(1196); + revision_stmts(); + setState(1197); + body_stmts(); + setState(1198); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static class Module_stmtContext extends ParserRuleContext { + public TerminalNode RIGHT_BRACE() { + return getToken(YangParser.RIGHT_BRACE, 0); + } + + public Linkage_stmtsContext linkage_stmts() { + return getRuleContext(Linkage_stmtsContext.class, 0); + } + + public Revision_stmtsContext revision_stmts() { + return getRuleContext(Revision_stmtsContext.class, 0); + } + + public StringContext string() { + return getRuleContext(StringContext.class, 0); + } + + public Body_stmtsContext body_stmts() { + return getRuleContext(Body_stmtsContext.class, 0); + } + + public Module_header_stmtsContext module_header_stmts() { + return getRuleContext(Module_header_stmtsContext.class, 0); + } + + public TerminalNode MODULE_KEYWORD() { + return getToken(YangParser.MODULE_KEYWORD, 0); + } + + public TerminalNode LEFT_BRACE() { + return getToken(YangParser.LEFT_BRACE, 0); + } + + public Meta_stmtsContext meta_stmts() { + return getRuleContext(Meta_stmtsContext.class, 0); + } + + public Module_stmtContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() { + return RULE_module_stmt; + } + + @Override + public void enterRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).enterModule_stmt(this); + } + + @Override + public void exitRule(ParseTreeListener listener) { + if (listener instanceof YangParserListener) + ((YangParserListener) listener).exitModule_stmt(this); + } + + @Override + public T accept(ParseTreeVisitor visitor) { + if (visitor instanceof YangParserVisitor) + return ((YangParserVisitor) visitor) + .visitModule_stmt(this); + else + return visitor.visitChildren(this); + } + } + + public final Module_stmtContext module_stmt() throws RecognitionException { + Module_stmtContext _localctx = new Module_stmtContext(_ctx, getState()); + enterRule(_localctx, 210, RULE_module_stmt); + try { + enterOuterAlt(_localctx, 1); + { + setState(1200); + match(MODULE_KEYWORD); + setState(1201); + string(); + setState(1202); + match(LEFT_BRACE); + setState(1203); + module_header_stmts(); + setState(1204); + linkage_stmts(); + setState(1205); + meta_stmts(); + setState(1206); + revision_stmts(); + setState(1207); + body_stmts(); + setState(1208); + match(RIGHT_BRACE); + } + } catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } finally { + exitRule(); + } + return _localctx; + } + + public static final String _serializedATN = "\2\3M\u04bd\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4" + + "\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20" + + "\4\21\t\21\4\22\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27" + + "\4\30\t\30\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36" + + "\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4" + + ")\t)\4*\t*\4+\t+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62" + + "\4\63\t\63\4\64\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4" + + ";\t;\4<\t<\4=\t=\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\t" + + "F\4G\tG\4H\tH\4I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4" + + "R\tR\4S\tS\4T\tT\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]" + + "\t]\4^\t^\4_\t_\4`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th" + + "\4i\ti\4j\tj\4k\tk\3\2\3\2\5\2\u00d9\n\2\3\3\3\3\3\3\7\3\u00de\n\3\f\3" + + "\16\3\u00e1\13\3\3\4\3\4\5\4\u00e5\n\4\3\4\3\4\3\5\3\5\5\5\u00eb\n\5\3" + + "\5\3\5\5\5\u00ef\n\5\3\5\5\5\u00f2\n\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6" + + "\3\6\3\6\3\6\7\6\u00ff\n\6\f\6\16\6\u0102\13\6\3\6\5\6\u0105\n\6\3\7\3" + + "\7\3\7\3\7\3\7\3\7\3\7\3\7\7\7\u010f\n\7\f\7\16\7\u0112\13\7\3\7\5\7\u0115" + + "\n\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\7\b\u0123\n\b\f\b" + + "\16\b\u0126\13\b\3\b\5\b\u0129\n\b\3\t\3\t\3\t\3\t\3\t\5\t\u0130\n\t\3" + + "\t\5\t\u0133\n\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\6\n\u013e\n\n\r\n" + + "\16\n\u013f\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13" + + "\3\13\7\13\u014f\n\13\f\13\16\13\u0152\13\13\3\13\5\13\u0155\n\13\3\f" + + "\3\f\3\f\3\f\3\f\6\f\u015c\n\f\r\f\16\f\u015d\3\f\3\f\3\r\3\r\3\r\3\r" + + "\3\r\6\r\u0167\n\r\r\r\16\r\u0168\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16" + + "\3\16\3\16\3\16\3\16\3\16\3\16\7\16\u0179\n\16\f\16\16\16\u017c\13\16" + + "\3\16\5\16\u017f\n\16\3\17\3\17\3\17\3\17\3\17\3\17\7\17\u0187\n\17\f" + + "\17\16\17\u018a\13\17\3\17\5\17\u018d\n\17\3\20\3\20\3\20\3\20\3\20\3" + + "\20\3\20\3\20\3\20\3\20\3\20\6\20\u019a\n\20\r\20\16\20\u019b\3\20\3\20" + + "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\6\21\u01ab\n\21" + + "\r\21\16\21\u01ac\3\21\3\21\3\22\3\22\3\22\3\22\3\22\7\22\u01b6\n\22\f" + + "\22\16\22\u01b9\13\22\3\23\3\23\7\23\u01bd\n\23\f\23\16\23\u01c0\13\23" + + "\3\24\3\24\3\24\3\24\3\24\7\24\u01c7\n\24\f\24\16\24\u01ca\13\24\3\25" + + "\3\25\3\25\3\25\3\25\3\25\7\25\u01d2\n\25\f\25\16\25\u01d5\13\25\3\26" + + "\3\26\3\26\3\26\3\26\3\26\7\26\u01dd\n\26\f\26\16\26\u01e0\13\26\3\27" + + "\3\27\3\27\3\27\3\27\3\27\7\27\u01e8\n\27\f\27\16\27\u01eb\13\27\3\30" + + "\3\30\3\30\3\30\3\30\7\30\u01f2\n\30\f\30\16\30\u01f5\13\30\3\31\3\31" + + "\3\31\3\31\3\31\3\31\3\31\5\31\u01fe\n\31\3\32\3\32\3\32\3\32\3\32\6\32" + + "\u0205\n\32\r\32\16\32\u0206\3\32\3\32\5\32\u020b\n\32\3\33\3\33\3\33" + + "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\7\33\u0219\n\33\f\33\16" + + "\33\u021c\13\33\3\33\5\33\u021f\n\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34" + + "\3\34\3\34\3\34\3\34\3\34\3\34\7\34\u022e\n\34\f\34\16\34\u0231\13\34" + + "\3\34\5\34\u0234\n\34\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35" + + "\3\35\7\35\u0241\n\35\f\35\16\35\u0244\13\35\3\35\5\35\u0247\n\35\3\36" + + "\3\36\3\36\3\36\3\36\5\36\u024e\n\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37" + + "\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\7\37\u025f\n\37\f\37\16\37\u0262" + + "\13\37\3\37\5\37\u0265\n\37\3 \3 \3 \3 \3!\3!\3!\3!\3\"\3\"\3\"\3\"\3" + + "\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\6\"\u0282\n" + + "\"\r\"\16\"\u0283\3\"\3\"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3" + + "#\3#\7#\u0298\n#\f#\16#\u029b\13#\3#\3#\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$" + + "\3$\3$\3$\3$\3$\7$\u02ae\n$\f$\16$\u02b1\13$\3$\3$\3%\3%\3%\3%\3%\3%\3" + + "%\3%\3%\3%\3%\3%\3%\3%\3%\3%\7%\u02c5\n%\f%\16%\u02c8\13%\3%\5%\u02cb" + + "\n%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\7&\u02d8\n&\f&\16&\u02db\13&\3&\5" + + "&\u02de\n&\3\'\3\'\3\'\3\'\3(\3(\3)\3)\3)\3)\3*\3*\3*\3*\3+\3+\3+\3+\3" + + ",\3,\3,\3,\3-\3-\3-\3-\3-\3-\3-\3-\3-\7-\u02ff\n-\f-\16-\u0302\13-\3-" + + "\5-\u0305\n-\3.\3.\3/\3/\3/\3/\3\60\3\60\3\60\3\60\3\61\3\61\3\62\3\62" + + "\3\62\3\62\3\63\3\63\3\64\3\64\3\64\3\64\3\65\3\65\3\66\3\66\3\66\3\66" + + "\3\67\3\67\3\67\3\67\38\38\38\38\38\38\38\38\38\78\u0330\n8\f8\168\u0333" + + "\138\38\58\u0336\n8\39\69\u0339\n9\r9\169\u033a\3:\6:\u033e\n:\r:\16:" + + "\u033f\3;\3;\3<\5<\u0345\n<\3=\3=\3>\3>\3>\3>\3?\3?\3?\3?\3@\3@\3A\3A" + + "\3A\3A\3A\3A\3A\3A\3A\7A\u035c\nA\fA\16A\u035f\13A\3A\5A\u0362\nA\3B\6" + + "B\u0365\nB\rB\16B\u0366\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3D\7D\u0376" + + "\nD\fD\16D\u0379\13D\3D\5D\u037c\nD\3E\3E\3E\3E\3E\3E\3E\3E\3E\7E\u0387" + + "\nE\fE\16E\u038a\13E\3E\5E\u038d\nE\3F\3F\7F\u0391\nF\fF\16F\u0394\13" + + "F\3G\3G\3G\3G\3H\5H\u039b\nH\3H\3H\3H\5H\u03a0\nH\5H\u03a2\nH\3I\3I\3" + + "I\3I\3I\3I\3I\3I\3I\7I\u03ad\nI\fI\16I\u03b0\13I\3I\5I\u03b3\nI\3J\3J" + + "\3K\3K\3K\3K\3K\3K\3K\3K\3K\5K\u03c0\nK\3L\3L\3L\3L\3L\3L\3L\5L\u03c9" + + "\nL\3M\3M\3M\3M\3M\3M\3M\3M\3M\6M\u03d4\nM\rM\16M\u03d5\3M\3M\3N\3N\3" + + "N\3N\3O\3O\3O\3O\3O\3O\3O\3O\7O\u03e6\nO\fO\16O\u03e9\13O\3O\5O\u03ec" + + "\nO\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\7Q\u03fa\nQ\fQ\16Q\u03fd\13Q\3" + + "Q\5Q\u0400\nQ\3R\3R\3S\3S\3S\3S\3T\3T\3T\3T\3T\5T\u040d\nT\3T\5T\u0410" + + "\nT\3U\3U\3U\3U\3U\3U\3U\3U\7U\u041a\nU\fU\16U\u041d\13U\3U\5U\u0420\n" + + "U\3V\3V\3V\3V\3W\3W\3W\3W\3W\5W\u042b\nW\3W\5W\u042e\nW\3W\5W\u0431\n" + + "W\3X\3X\3X\3X\3Y\3Y\3Y\3Y\3Z\3Z\3Z\3Z\3[\3[\3[\3[\3\\\3\\\3\\\3\\\3]\3" + + "]\3]\3]\3]\3]\3^\3^\3^\3^\3_\3_\3_\3_\3`\3`\3`\3`\3`\5`\u045a\n`\3`\5" + + "`\u045d\n`\3a\3a\3a\3a\3a\5a\u0464\na\3a\3a\3b\3b\3b\3b\3c\3c\3c\3c\3" + + "c\3c\3c\5c\u0473\nc\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\5d\u047f\nd\7d\u0481" + + "\nd\fd\16d\u0484\13d\3e\7e\u0487\ne\fe\16e\u048a\13e\3f\3f\7f\u048e\n" + + "f\ff\16f\u0491\13f\3g\3g\3g\3g\7g\u0497\ng\fg\16g\u049a\13g\3h\3h\6h\u049e" + + "\nh\rh\16h\u049f\3i\3i\3i\6i\u04a5\ni\ri\16i\u04a6\3j\3j\3j\3j\3j\3j\3" + + "j\3j\3j\3j\3k\3k\3k\3k\3k\3k\3k\3k\3k\3k\3k\2l\2\4\6\b\n\f\16\20\22\24" + + "\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtv" + + "xz|~\u0080\u0082\u0084\u0086\u0088\u008a\u008c\u008e\u0090\u0092\u0094" + + "\u0096\u0098\u009a\u009c\u009e\u00a0\u00a2\u00a4\u00a6\u00a8\u00aa\u00ac" + + "\u00ae\u00b0\u00b2\u00b4\u00b6\u00b8\u00ba\u00bc\u00be\u00c0\u00c2\u00c4" + + "\u00c6\u00c8\u00ca\u00cc\u00ce\u00d0\u00d2\u00d4\2\2\u05a3\2\u00d8\3\2" + + "\2\2\4\u00da\3\2\2\2\6\u00e2\3\2\2\2\b\u00f1\3\2\2\2\n\u00f3\3\2\2\2\f" + + "\u0106\3\2\2\2\16\u0116\3\2\2\2\20\u012a\3\2\2\2\22\u0134\3\2\2\2\24\u0143" + + "\3\2\2\2\26\u0156\3\2\2\2\30\u0161\3\2\2\2\32\u016c\3\2\2\2\34\u0180\3" + + "\2\2\2\36\u018e\3\2\2\2 \u019f\3\2\2\2\"\u01b7\3\2\2\2$\u01be\3\2\2\2" + + "&\u01c8\3\2\2\2(\u01d3\3\2\2\2*\u01de\3\2\2\2,\u01e9\3\2\2\2.\u01f3\3" + + "\2\2\2\60\u01fd\3\2\2\2\62\u01ff\3\2\2\2\64\u020c\3\2\2\2\66\u0220\3\2" + + "\2\28\u0235\3\2\2\2:\u024d\3\2\2\2<\u024f\3\2\2\2>\u0266\3\2\2\2@\u026a" + + "\3\2\2\2B\u026e\3\2\2\2D\u0287\3\2\2\2F\u029e\3\2\2\2H\u02b4\3\2\2\2J" + + "\u02cc\3\2\2\2L\u02df\3\2\2\2N\u02e3\3\2\2\2P\u02e5\3\2\2\2R\u02e9\3\2" + + "\2\2T\u02ed\3\2\2\2V\u02f1\3\2\2\2X\u02f5\3\2\2\2Z\u0306\3\2\2\2\\\u0308" + + "\3\2\2\2^\u030c\3\2\2\2`\u0310\3\2\2\2b\u0312\3\2\2\2d\u0316\3\2\2\2f" + + "\u0318\3\2\2\2h\u031c\3\2\2\2j\u031e\3\2\2\2l\u0322\3\2\2\2n\u0326\3\2" + + "\2\2p\u0338\3\2\2\2r\u033d\3\2\2\2t\u0341\3\2\2\2v\u0344\3\2\2\2x\u0346" + + "\3\2\2\2z\u0348\3\2\2\2|\u034c\3\2\2\2~\u0350\3\2\2\2\u0080\u0352\3\2" + + "\2\2\u0082\u0364\3\2\2\2\u0084\u0368\3\2\2\2\u0086\u036c\3\2\2\2\u0088" + + "\u037d\3\2\2\2\u008a\u0392\3\2\2\2\u008c\u0395\3\2\2\2\u008e\u03a1\3\2" + + "\2\2\u0090\u03a3\3\2\2\2\u0092\u03b4\3\2\2\2\u0094\u03bf\3\2\2\2\u0096" + + "\u03c1\3\2\2\2\u0098\u03ca\3\2\2\2\u009a\u03d9\3\2\2\2\u009c\u03dd\3\2" + + "\2\2\u009e\u03ed\3\2\2\2\u00a0\u03f1\3\2\2\2\u00a2\u0401\3\2\2\2\u00a4" + + "\u0403\3\2\2\2\u00a6\u0407\3\2\2\2\u00a8\u0411\3\2\2\2\u00aa\u0421\3\2" + + "\2\2\u00ac\u0425\3\2\2\2\u00ae\u0432\3\2\2\2\u00b0\u0436\3\2\2\2\u00b2" + + "\u043a\3\2\2\2\u00b4\u043e\3\2\2\2\u00b6\u0442\3\2\2\2\u00b8\u0446\3\2" + + "\2\2\u00ba\u044c\3\2\2\2\u00bc\u0450\3\2\2\2\u00be\u0454\3\2\2\2\u00c0" + + "\u045e\3\2\2\2\u00c2\u0467\3\2\2\2\u00c4\u0472\3\2\2\2\u00c6\u0482\3\2" + + "\2\2\u00c8\u0488\3\2\2\2\u00ca\u048f\3\2\2\2\u00cc\u0498\3\2\2\2\u00ce" + + "\u049d\3\2\2\2\u00d0\u04a4\3\2\2\2\u00d2\u04a8\3\2\2\2\u00d4\u04b2\3\2" + + "\2\2\u00d6\u00d9\5\u00d4k\2\u00d7\u00d9\5\u00d2j\2\u00d8\u00d6\3\2\2\2" + + "\u00d8\u00d7\3\2\2\2\u00d9\3\3\2\2\2\u00da\u00df\7L\2\2\u00db\u00dc\7" + + "\6\2\2\u00dc\u00de\7L\2\2\u00dd\u00db\3\2\2\2\u00de\u00e1\3\2\2\2\u00df" + + "\u00dd\3\2\2\2\u00df\u00e0\3\2\2\2\u00e0\5\3\2\2\2\u00e1\u00df\3\2\2\2" + + "\u00e2\u00e4\7K\2\2\u00e3\u00e5\5\4\3\2\u00e4\u00e3\3\2\2\2\u00e4\u00e5" + + "\3\2\2\2\u00e5\u00e6\3\2\2\2\u00e6\u00e7\5\b\5\2\u00e7\7\3\2\2\2\u00e8" + + "\u00ea\7\3\2\2\u00e9\u00eb\5\6\4\2\u00ea\u00e9\3\2\2\2\u00ea\u00eb\3\2" + + "\2\2\u00eb\u00f2\3\2\2\2\u00ec\u00ee\7\4\2\2\u00ed\u00ef\5\6\4\2\u00ee" + + "\u00ed\3\2\2\2\u00ee\u00ef\3\2\2\2\u00ef\u00f0\3\2\2\2\u00f0\u00f2\7\5" + + "\2\2\u00f1\u00e8\3\2\2\2\u00f1\u00ec\3\2\2\2\u00f2\t\3\2\2\2\u00f3\u00f4" + + "\78\2\2\u00f4\u0104\5\4\3\2\u00f5\u0105\7\3\2\2\u00f6\u0100\7\4\2\2\u00f7" + + "\u00ff\5\u0096L\2\u00f8\u00ff\5\u00aeX\2\u00f9\u00ff\5\u0084C\2\u00fa" + + "\u00ff\5f\64\2\u00fb\u00ff\5b\62\2\u00fc\u00ff\5R*\2\u00fd\u00ff\5P)\2" + + "\u00fe\u00f7\3\2\2\2\u00fe\u00f8\3\2\2\2\u00fe\u00f9\3\2\2\2\u00fe\u00fa" + + "\3\2\2\2\u00fe\u00fb\3\2\2\2\u00fe\u00fc\3\2\2\2\u00fe\u00fd\3\2\2\2\u00ff" + + "\u0102\3\2\2\2\u0100\u00fe\3\2\2\2\u0100\u0101\3\2\2\2\u0101\u0103\3\2" + + "\2\2\u0102\u0100\3\2\2\2\u0103\u0105\7\5\2\2\u0104\u00f5\3\2\2\2\u0104" + + "\u00f6\3\2\2\2\u0105\13\3\2\2\2\u0106\u0107\78\2\2\u0107\u0114\5\4\3\2" + + "\u0108\u0115\7\3\2\2\u0109\u0110\7\4\2\2\u010a\u010f\5\u00aeX\2\u010b" + + "\u010f\5X-\2\u010c\u010f\5> \2\u010d\u010f\5\u0084C\2\u010e\u010a\3\2" + + "\2\2\u010e\u010b\3\2\2\2\u010e\u010c\3\2\2\2\u010e\u010d\3\2\2\2\u010f" + + "\u0112\3\2\2\2\u0110\u010e\3\2\2\2\u0110\u0111\3\2\2\2\u0111\u0113\3\2" + + "\2\2\u0112\u0110\3\2\2\2\u0113\u0115\7\5\2\2\u0114\u0108\3\2\2\2\u0114" + + "\u0109\3\2\2\2\u0115\r\3\2\2\2\u0116\u0117\78\2\2\u0117\u0128\5\4\3\2" + + "\u0118\u0129\7\3\2\2\u0119\u0124\7\4\2\2\u011a\u0123\5\u00aeX\2\u011b" + + "\u0123\5X-\2\u011c\u0123\5> \2\u011d\u0123\5\u0084C\2\u011e\u0123\5f\64" + + "\2\u011f\u0123\5b\62\2\u0120\u0123\5R*\2\u0121\u0123\5P)\2\u0122\u011a" + + "\3\2\2\2\u0122\u011b\3\2\2\2\u0122\u011c\3\2\2\2\u0122\u011d\3\2\2\2\u0122" + + "\u011e\3\2\2\2\u0122\u011f\3\2\2\2\u0122\u0120\3\2\2\2\u0122\u0121\3\2" + + "\2\2\u0123\u0126\3\2\2\2\u0124\u0122\3\2\2\2\u0124\u0125\3\2\2\2\u0125" + + "\u0127\3\2\2\2\u0126\u0124\3\2\2\2\u0127\u0129\7\5\2\2\u0128\u0118\3\2" + + "\2\2\u0128\u0119\3\2\2\2\u0129\17\3\2\2\2\u012a\u012b\78\2\2\u012b\u0132" + + "\5\4\3\2\u012c\u0133\7\3\2\2\u012d\u012f\7\4\2\2\u012e\u0130\5\6\4\2\u012f" + + "\u012e\3\2\2\2\u012f\u0130\3\2\2\2\u0130\u0131\3\2\2\2\u0131\u0133\7\5" + + "\2\2\u0132\u012c\3\2\2\2\u0132\u012d\3\2\2\2\u0133\21\3\2\2\2\u0134\u0135" + + "\79\2\2\u0135\u0136\5\4\3\2\u0136\u013d\7\4\2\2\u0137\u013e\5\u00b2Z\2" + + "\u0138\u013e\5\u00b0Y\2\u0139\u013e\5\20\t\2\u013a\u013e\5\16\b\2\u013b" + + "\u013e\5\n\6\2\u013c\u013e\5\f\7\2\u013d\u0137\3\2\2\2\u013d\u0138\3\2" + + "\2\2\u013d\u0139\3\2\2\2\u013d\u013a\3\2\2\2\u013d\u013b\3\2\2\2\u013d" + + "\u013c\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u013d\3\2\2\2\u013f\u0140\3\2" + + "\2\2\u0140\u0141\3\2\2\2\u0141\u0142\7\5\2\2\u0142\23\3\2\2\2\u0143\u0144" + + "\7$\2\2\u0144\u0154\5\4\3\2\u0145\u0155\7\3\2\2\u0146\u0150\7\4\2\2\u0147" + + "\u014f\5\u009aN\2\u0148\u014f\5j\66\2\u0149\u014f\5\u00b2Z\2\u014a\u014f" + + "\5\u00b0Y\2\u014b\u014f\5\u0098M\2\u014c\u014f\5J&\2\u014d\u014f\5\u00c4" + + "c\2\u014e\u0147\3\2\2\2\u014e\u0148\3\2\2\2\u014e\u0149\3\2\2\2\u014e" + + "\u014a\3\2\2\2\u014e\u014b\3\2\2\2\u014e\u014c\3\2\2\2\u014e\u014d\3\2" + + "\2\2\u014f\u0152\3\2\2\2\u0150\u014e\3\2\2\2\u0150\u0151\3\2\2\2\u0151" + + "\u0153\3\2\2\2\u0152\u0150\3\2\2\2\u0153\u0155\7\5\2\2\u0154\u0145\3\2" + + "\2\2\u0154\u0146\3\2\2\2\u0155\25\3\2\2\2\u0156\u0157\7!\2\2\u0157\u015b" + + "\7\4\2\2\u0158\u015c\5\u0098M\2\u0159\u015c\5J&\2\u015a\u015c\5\u00c4" + + "c\2\u015b\u0158\3\2\2\2\u015b\u0159\3\2\2\2\u015b\u015a\3\2\2\2\u015c" + + "\u015d\3\2\2\2\u015d\u015b\3\2\2\2\u015d\u015e\3\2\2\2\u015e\u015f\3\2" + + "\2\2\u015f\u0160\7\5\2\2\u0160\27\3\2\2\2\u0161\u0162\7\60\2\2\u0162\u0166" + + "\7\4\2\2\u0163\u0167\5\u0098M\2\u0164\u0167\5J&\2\u0165\u0167\5\u00c4" + + "c\2\u0166\u0163\3\2\2\2\u0166\u0164\3\2\2\2\u0166\u0165\3\2\2\2\u0167" + + "\u0168\3\2\2\2\u0168\u0166\3\2\2\2\u0168\u0169\3\2\2\2\u0169\u016a\3\2" + + "\2\2\u016a\u016b\7\5\2\2\u016b\31\3\2\2\2\u016c\u016d\7\25\2\2\u016d\u017e" + + "\5\4\3\2\u016e\u017f\7\3\2\2\u016f\u017a\7\4\2\2\u0170\u0179\5\u009aN" + + "\2\u0171\u0179\5j\66\2\u0172\u0179\5\u00b2Z\2\u0173\u0179\5\u00b0Y\2\u0174" + + "\u0179\5\u0098M\2\u0175\u0179\5J&\2\u0176\u0179\5\30\r\2\u0177\u0179\5" + + "\26\f\2\u0178\u0170\3\2\2\2\u0178\u0171\3\2\2\2\u0178\u0172\3\2\2\2\u0178" + + "\u0173\3\2\2\2\u0178\u0174\3\2\2\2\u0178\u0175\3\2\2\2\u0178\u0176\3\2" + + "\2\2\u0178\u0177\3\2\2\2\u0179\u017c\3\2\2\2\u017a\u0178\3\2\2\2\u017a" + + "\u017b\3\2\2\2\u017b\u017d\3\2\2\2\u017c\u017a\3\2\2\2\u017d\u017f\7\5" + + "\2\2\u017e\u016e\3\2\2\2\u017e\u016f\3\2\2\2\u017f\33\3\2\2\2\u0180\u0181" + + "\7\f\2\2\u0181\u018c\5\4\3\2\u0182\u018d\7\3\2\2\u0183\u0188\7\4\2\2\u0184" + + "\u0187\5\u00b2Z\2\u0185\u0187\5\u00b0Y\2\u0186\u0184\3\2\2\2\u0186\u0185" + + "\3\2\2\2\u0187\u018a\3\2\2\2\u0188\u0186\3\2\2\2\u0188\u0189\3\2\2\2\u0189" + + "\u018b\3\2\2\2\u018a\u0188\3\2\2\2\u018b\u018d\7\5\2\2\u018c\u0182\3\2" + + "\2\2\u018c\u0183\3\2\2\2\u018d\35\3\2\2\2\u018e\u018f\7H\2\2\u018f\u0190" + + "\5\4\3\2\u0190\u0199\7\4\2\2\u0191\u019a\5\6\4\2\u0192\u019a\5\34\17\2" + + "\u0193\u019a\5\u009aN\2\u0194\u019a\5j\66\2\u0195\u019a\5\u00b2Z\2\u0196" + + "\u019a\5\u00b0Y\2\u0197\u019a\5\u00c4c\2\u0198\u019a\58\35\2\u0199\u0191" + + "\3\2\2\2\u0199\u0192\3\2\2\2\u0199\u0193\3\2\2\2\u0199\u0194\3\2\2\2\u0199" + + "\u0195\3\2\2\2\u0199\u0196\3\2\2\2\u0199\u0197\3\2\2\2\u0199\u0198\3\2" + + "\2\2\u019a\u019b\3\2\2\2\u019b\u0199\3\2\2\2\u019b\u019c\3\2\2\2\u019c" + + "\u019d\3\2\2\2\u019d\u019e\7\5\2\2\u019e\37\3\2\2\2\u019f\u01a0\7H\2\2" + + "\u01a0\u01a1\5\4\3\2\u01a1\u01aa\7\4\2\2\u01a2\u01ab\5\6\4\2\u01a3\u01ab" + + "\5\34\17\2\u01a4\u01ab\5\u009aN\2\u01a5\u01ab\5j\66\2\u01a6\u01ab\5\u00b2" + + "Z\2\u01a7\u01ab\5\u00b0Y\2\u01a8\u01ab\5\u00c4c\2\u01a9\u01ab\58\35\2" + + "\u01aa\u01a2\3\2\2\2\u01aa\u01a3\3\2\2\2\u01aa\u01a4\3\2\2\2\u01aa\u01a5" + + "\3\2\2\2\u01aa\u01a6\3\2\2\2\u01aa\u01a7\3\2\2\2\u01aa\u01a8\3\2\2\2\u01aa" + + "\u01a9\3\2\2\2\u01ab\u01ac\3\2\2\2\u01ac\u01aa\3\2\2\2\u01ac\u01ad\3\2" + + "\2\2\u01ad\u01ae\3\2\2\2\u01ae\u01af\7\5\2\2\u01af!\3\2\2\2\u01b0\u01b6" + + "\5X-\2\u01b1\u01b6\5f\64\2\u01b2\u01b6\5b\62\2\u01b3\u01b6\5\u00b2Z\2" + + "\u01b4\u01b6\5\u00b0Y\2\u01b5\u01b0\3\2\2\2\u01b5\u01b1\3\2\2\2\u01b5" + + "\u01b2\3\2\2\2\u01b5\u01b3\3\2\2\2\u01b5\u01b4\3\2\2\2\u01b6\u01b9\3\2" + + "\2\2\u01b7\u01b5\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8#\3\2\2\2\u01b9\u01b7" + + "\3\2\2\2\u01ba\u01bd\5\u00b2Z\2\u01bb\u01bd\5\u00b0Y\2\u01bc\u01ba\3\2" + + "\2\2\u01bc\u01bb\3\2\2\2\u01bd\u01c0\3\2\2\2\u01be\u01bc\3\2\2\2\u01be" + + "\u01bf\3\2\2\2\u01bf%\3\2\2\2\u01c0\u01be\3\2\2\2\u01c1\u01c7\5\u0084" + + "C\2\u01c2\u01c7\5f\64\2\u01c3\u01c7\5b\62\2\u01c4\u01c7\5\u00b2Z\2\u01c5" + + "\u01c7\5\u00b0Y\2\u01c6\u01c1\3\2\2\2\u01c6\u01c2\3\2\2\2\u01c6\u01c3" + + "\3\2\2\2\u01c6\u01c4\3\2\2\2\u01c6\u01c5\3\2\2\2\u01c7\u01ca\3\2\2\2\u01c8" + + "\u01c6\3\2\2\2\u01c8\u01c9\3\2\2\2\u01c9\'\3\2\2\2\u01ca\u01c8\3\2\2\2" + + "\u01cb\u01d2\5X-\2\u01cc\u01d2\5f\64\2\u01cd\u01d2\5R*\2\u01ce\u01d2\5" + + "P)\2\u01cf\u01d2\5\u00b2Z\2\u01d0\u01d2\5\u00b0Y\2\u01d1\u01cb\3\2\2\2" + + "\u01d1\u01cc\3\2\2\2\u01d1\u01cd\3\2\2\2\u01d1\u01ce\3\2\2\2\u01d1\u01cf" + + "\3\2\2\2\u01d1\u01d0\3\2\2\2\u01d2\u01d5\3\2\2\2\u01d3\u01d1\3\2\2\2\u01d3" + + "\u01d4\3\2\2\2\u01d4)\3\2\2\2\u01d5\u01d3\3\2\2\2\u01d6\u01dd\5X-\2\u01d7" + + "\u01dd\5f\64\2\u01d8\u01dd\5R*\2\u01d9\u01dd\5P)\2\u01da\u01dd\5\u00b2" + + "Z\2\u01db\u01dd\5\u00b0Y\2\u01dc\u01d6\3\2\2\2\u01dc\u01d7\3\2\2\2\u01dc" + + "\u01d8\3\2\2\2\u01dc\u01d9\3\2\2\2\u01dc\u01da\3\2\2\2\u01dc\u01db\3\2" + + "\2\2\u01dd\u01e0\3\2\2\2\u01de\u01dc\3\2\2\2\u01de\u01df\3\2\2\2\u01df" + + "+\3\2\2\2\u01e0\u01de\3\2\2\2\u01e1\u01e8\5X-\2\u01e2\u01e8\5\u0084C\2" + + "\u01e3\u01e8\5f\64\2\u01e4\u01e8\5b\62\2\u01e5\u01e8\5\u00b2Z\2\u01e6" + + "\u01e8\5\u00b0Y\2\u01e7\u01e1\3\2\2\2\u01e7\u01e2\3\2\2\2\u01e7\u01e3" + + "\3\2\2\2\u01e7\u01e4\3\2\2\2\u01e7\u01e5\3\2\2\2\u01e7\u01e6\3\2\2\2\u01e8" + + "\u01eb\3\2\2\2\u01e9\u01e7\3\2\2\2\u01e9\u01ea\3\2\2\2\u01ea-\3\2\2\2" + + "\u01eb\u01e9\3\2\2\2\u01ec\u01f2\5X-\2\u01ed\u01f2\5^\60\2\u01ee\u01f2" + + "\5f\64\2\u01ef\u01f2\5\u00b2Z\2\u01f0\u01f2\5\u00b0Y\2\u01f1\u01ec\3\2" + + "\2\2\u01f1\u01ed\3\2\2\2\u01f1\u01ee\3\2\2\2\u01f1\u01ef\3\2\2\2\u01f1" + + "\u01f0\3\2\2\2\u01f2\u01f5\3\2\2\2\u01f3\u01f1\3\2\2\2\u01f3\u01f4\3\2" + + "\2\2\u01f4/\3\2\2\2\u01f5\u01f3\3\2\2\2\u01f6\u01fe\5.\30\2\u01f7\u01fe" + + "\5,\27\2\u01f8\u01fe\5*\26\2\u01f9\u01fe\5(\25\2\u01fa\u01fe\5&\24\2\u01fb" + + "\u01fe\5$\23\2\u01fc\u01fe\5\"\22\2\u01fd\u01f6\3\2\2\2\u01fd\u01f7\3" + + "\2\2\2\u01fd\u01f8\3\2\2\2\u01fd\u01f9\3\2\2\2\u01fd\u01fa\3\2\2\2\u01fd" + + "\u01fb\3\2\2\2\u01fd\u01fc\3\2\2\2\u01fe\61\3\2\2\2\u01ff\u0200\7\31\2" + + "\2\u0200\u020a\5\4\3\2\u0201\u020b\7\3\2\2\u0202\u0204\7\4\2\2\u0203\u0205" + + "\5\60\31\2\u0204\u0203\3\2\2\2\u0205\u0206\3\2\2\2\u0206\u0204\3\2\2\2" + + "\u0206\u0207\3\2\2\2\u0207\u0208\3\2\2\2\u0208\u0209\7\5\2\2\u0209\u020b" + + "\3\2\2\2\u020a\u0201\3\2\2\2\u020a\u0202\3\2\2\2\u020b\63\3\2\2\2\u020c" + + "\u020d\7\16\2\2\u020d\u021e\5\4\3\2\u020e\u021f\7\3\2\2\u020f\u021a\7" + + "\4\2\2\u0210\u0219\5\6\4\2\u0211\u0219\5\34\17\2\u0212\u0219\5\u009aN" + + "\2\u0213\u0219\5j\66\2\u0214\u0219\5\u00b2Z\2\u0215\u0219\5\u00b0Y\2\u0216" + + "\u0219\5\62\32\2\u0217\u0219\5 \21\2\u0218\u0210\3\2\2\2\u0218\u0211\3" + + "\2\2\2\u0218\u0212\3\2\2\2\u0218\u0213\3\2\2\2\u0218\u0214\3\2\2\2\u0218" + + "\u0215\3\2\2\2\u0218\u0216\3\2\2\2\u0218\u0217\3\2\2\2\u0219\u021c\3\2" + + "\2\2\u021a\u0218\3\2\2\2\u021a\u021b\3\2\2\2\u021b\u021d\3\2\2\2\u021c" + + "\u021a\3\2\2\2\u021d\u021f\7\5\2\2\u021e\u020e\3\2\2\2\u021e\u020f\3\2" + + "\2\2\u021f\65\3\2\2\2\u0220\u0221\7J\2\2\u0221\u0233\5\4\3\2\u0222\u0234" + + "\7\3\2\2\u0223\u022f\7\4\2\2\u0224\u022e\5\6\4\2\u0225\u022e\5\34\17\2" + + "\u0226\u022e\5\u009aN\2\u0227\u022e\5X-\2\u0228\u022e\5f\64\2\u0229\u022e" + + "\5b\62\2\u022a\u022e\5j\66\2\u022b\u022e\5\u00b2Z\2\u022c\u022e\5\u00b0" + + "Y\2\u022d\u0224\3\2\2\2\u022d\u0225\3\2\2\2\u022d\u0226\3\2\2\2\u022d" + + "\u0227\3\2\2\2\u022d\u0228\3\2\2\2\u022d\u0229\3\2\2\2\u022d\u022a\3\2" + + "\2\2\u022d\u022b\3\2\2\2\u022d\u022c\3\2\2\2\u022e\u0231\3\2\2\2\u022f" + + "\u022d\3\2\2\2\u022f\u0230\3\2\2\2\u0230\u0232\3\2\2\2\u0231\u022f\3\2" + + "\2\2\u0232\u0234\7\5\2\2\u0233\u0222\3\2\2\2\u0233\u0223\3\2\2\2\u0234" + + "\67\3\2\2\2\u0235\u0236\7D\2\2\u0236\u0246\5\4\3\2\u0237\u0247\7\3\2\2" + + "\u0238\u0242\7\4\2\2\u0239\u0241\5\6\4\2\u023a\u0241\5\34\17\2\u023b\u0241" + + "\5\u009aN\2\u023c\u0241\5j\66\2\u023d\u0241\5\u00b2Z\2\u023e\u0241\5\u00b0" + + "Y\2\u023f\u0241\5\u00c4c\2\u0240\u0239\3\2\2\2\u0240\u023a\3\2\2\2\u0240" + + "\u023b\3\2\2\2\u0240\u023c\3\2\2\2\u0240\u023d\3\2\2\2\u0240\u023e\3\2" + + "\2\2\u0240\u023f\3\2\2\2\u0241\u0244\3\2\2\2\u0242\u0240\3\2\2\2\u0242" + + "\u0243\3\2\2\2\u0243\u0245\3\2\2\2\u0244\u0242\3\2\2\2\u0245\u0247\7\5" + + "\2\2\u0246\u0237\3\2\2\2\u0246\u0238\3\2\2\2\u02479\3\2\2\2\u0248\u024e" + + "\5H%\2\u0249\u024e\5F$\2\u024a\u024e\5D#\2\u024b\u024e\5B\"\2\u024c\u024e" + + "\5\66\34\2\u024d\u0248\3\2\2\2\u024d\u0249\3\2\2\2\u024d\u024a\3\2\2\2" + + "\u024d\u024b\3\2\2\2\u024d\u024c\3\2\2\2\u024e;\3\2\2\2\u024f\u0250\7" + + "C\2\2\u0250\u0264\5\4\3\2\u0251\u0265\7\3\2\2\u0252\u0260\7\4\2\2\u0253" + + "\u025f\5\6\4\2\u0254\u025f\5\34\17\2\u0255\u025f\5\u009aN\2\u0256\u025f" + + "\5\u0084C\2\u0257\u025f\5f\64\2\u0258\u025f\5b\62\2\u0259\u025f\5j\66" + + "\2\u025a\u025f\5\u00b2Z\2\u025b\u025f\5\u00b0Y\2\u025c\u025f\5:\36\2\u025d" + + "\u025f\58\35\2\u025e\u0253\3\2\2\2\u025e\u0254\3\2\2\2\u025e\u0255\3\2" + + "\2\2\u025e\u0256\3\2\2\2\u025e\u0257\3\2\2\2\u025e\u0258\3\2\2\2\u025e" + + "\u0259\3\2\2\2\u025e\u025a\3\2\2\2\u025e\u025b\3\2\2\2\u025e\u025c\3\2" + + "\2\2\u025e\u025d\3\2\2\2\u025f\u0262\3\2\2\2\u0260\u025e\3\2\2\2\u0260" + + "\u0261\3\2\2\2\u0261\u0263\3\2\2\2\u0262\u0260\3\2\2\2\u0263\u0265\7\5" + + "\2\2\u0264\u0251\3\2\2\2\u0264\u0252\3\2\2\2\u0265=\3\2\2\2\u0266\u0267" + + "\7\20\2\2\u0267\u0268\5\4\3\2\u0268\u0269\5\b\5\2\u0269?\3\2\2\2\u026a" + + "\u026b\7/\2\2\u026b\u026c\5\4\3\2\u026c\u026d\5\b\5\2\u026dA\3\2\2\2\u026e" + + "\u026f\7+\2\2\u026f\u0270\5\4\3\2\u0270\u0281\7\4\2\2\u0271\u0282\5\6" + + "\4\2\u0272\u0282\5\34\17\2\u0273\u0282\5\u009aN\2\u0274\u0282\5X-\2\u0275" + + "\u0282\5@!\2\u0276\u0282\5> \2\u0277\u0282\5f\64\2\u0278\u0282\5R*\2\u0279" + + "\u0282\5P)\2\u027a\u0282\5\\/\2\u027b\u0282\5j\66\2\u027c\u0282\5\u00b2" + + "Z\2\u027d\u0282\5\u00b0Y\2\u027e\u0282\5\u0098M\2\u027f\u0282\5J&\2\u0280" + + "\u0282\5\u00c4c\2\u0281\u0271\3\2\2\2\u0281\u0272\3\2\2\2\u0281\u0273" + + "\3\2\2\2\u0281\u0274\3\2\2\2\u0281\u0275\3\2\2\2\u0281\u0276\3\2\2\2\u0281" + + "\u0277\3\2\2\2\u0281\u0278\3\2\2\2\u0281\u0279\3\2\2\2\u0281\u027a\3\2" + + "\2\2\u0281\u027b\3\2\2\2\u0281\u027c\3\2\2\2\u0281\u027d\3\2\2\2\u0281" + + "\u027e\3\2\2\2\u0281\u027f\3\2\2\2\u0281\u0280\3\2\2\2\u0282\u0283\3\2" + + "\2\2\u0283\u0281\3\2\2\2\u0283\u0284\3\2\2\2\u0284\u0285\3\2\2\2\u0285" + + "\u0286\7\5\2\2\u0286C\3\2\2\2\u0287\u0288\7-\2\2\u0288\u0289\5\4\3\2\u0289" + + "\u0299\7\4\2\2\u028a\u0298\5\6\4\2\u028b\u0298\5\34\17\2\u028c\u0298\5" + + "\u009aN\2\u028d\u0298\5\u0096L\2\u028e\u0298\5\u00aeX\2\u028f\u0298\5" + + "X-\2\u0290\u0298\5f\64\2\u0291\u0298\5R*\2\u0292\u0298\5P)\2\u0293\u0298" + + "\5\\/\2\u0294\u0298\5j\66\2\u0295\u0298\5\u00b2Z\2\u0296\u0298\5\u00b0" + + "Y\2\u0297\u028a\3\2\2\2\u0297\u028b\3\2\2\2\u0297\u028c\3\2\2\2\u0297" + + "\u028d\3\2\2\2\u0297\u028e\3\2\2\2\u0297\u028f\3\2\2\2\u0297\u0290\3\2" + + "\2\2\u0297\u0291\3\2\2\2\u0297\u0292\3\2\2\2\u0297\u0293\3\2\2\2\u0297" + + "\u0294\3\2\2\2\u0297\u0295\3\2\2\2\u0297\u0296\3\2\2\2\u0298\u029b\3\2" + + "\2\2\u0299\u0297\3\2\2\2\u0299\u029a\3\2\2\2\u029a\u029c\3\2\2\2\u029b" + + "\u0299\3\2\2\2\u029c\u029d\7\5\2\2\u029dE\3\2\2\2\u029e\u029f\7.\2\2\u029f" + + "\u02a0\5\4\3\2\u02a0\u02af\7\4\2\2\u02a1\u02ae\5\6\4\2\u02a2\u02ae\5\34" + + "\17\2\u02a3\u02ae\5\u009aN\2\u02a4\u02ae\5\u0096L\2\u02a5\u02ae\5\u00ae" + + "X\2\u02a6\u02ae\5X-\2\u02a7\u02ae\5\u0084C\2\u02a8\u02ae\5f\64\2\u02a9" + + "\u02ae\5b\62\2\u02aa\u02ae\5j\66\2\u02ab\u02ae\5\u00b2Z\2\u02ac\u02ae" + + "\5\u00b0Y\2\u02ad\u02a1\3\2\2\2\u02ad\u02a2\3\2\2\2\u02ad\u02a3\3\2\2" + + "\2\u02ad\u02a4\3\2\2\2\u02ad\u02a5\3\2\2\2\u02ad\u02a6\3\2\2\2\u02ad\u02a7" + + "\3\2\2\2\u02ad\u02a8\3\2\2\2\u02ad\u02a9\3\2\2\2\u02ad\u02aa\3\2\2\2\u02ad" + + "\u02ab\3\2\2\2\u02ad\u02ac\3\2\2\2\u02ae\u02b1\3\2\2\2\u02af\u02ad\3\2" + + "\2\2\u02af\u02b0\3\2\2\2\u02b0\u02b2\3\2\2\2\u02b1\u02af\3\2\2\2\u02b2" + + "\u02b3\7\5\2\2\u02b3G\3\2\2\2\u02b4\u02b5\7@\2\2\u02b5\u02ca\5\4\3\2\u02b6" + + "\u02cb\7\3\2\2\u02b7\u02c6\7\4\2\2\u02b8\u02c5\5\6\4\2\u02b9\u02c5\5\34" + + "\17\2\u02ba\u02c5\5\u009aN\2\u02bb\u02c5\5X-\2\u02bc\u02c5\5^\60\2\u02bd" + + "\u02c5\5f\64\2\u02be\u02c5\5j\66\2\u02bf\u02c5\5\u00b2Z\2\u02c0\u02c5" + + "\5\u00b0Y\2\u02c1\u02c5\5\u0098M\2\u02c2\u02c5\5J&\2\u02c3\u02c5\5\u00c4" + + "c\2\u02c4\u02b8\3\2\2\2\u02c4\u02b9\3\2\2\2\u02c4\u02ba\3\2\2\2\u02c4" + + "\u02bb\3\2\2\2\u02c4\u02bc\3\2\2\2\u02c4\u02bd\3\2\2\2\u02c4\u02be\3\2" + + "\2\2\u02c4\u02bf\3\2\2\2\u02c4\u02c0\3\2\2\2\u02c4\u02c1\3\2\2\2\u02c4" + + "\u02c2\3\2\2\2\u02c4\u02c3\3\2\2\2\u02c5\u02c8\3\2\2\2\u02c6\u02c4\3\2" + + "\2\2\u02c6\u02c7\3\2\2\2\u02c7\u02c9\3\2\2\2\u02c8\u02c6\3\2\2\2\u02c9" + + "\u02cb\7\5\2\2\u02ca\u02b6\3\2\2\2\u02ca\u02b7\3\2\2\2\u02cbI\3\2\2\2" + + "\u02cc\u02cd\7\65\2\2\u02cd\u02dd\5\4\3\2\u02ce\u02de\7\3\2\2\u02cf\u02d9" + + "\7\4\2\2\u02d0\u02d8\5\6\4\2\u02d1\u02d8\5j\66\2\u02d2\u02d8\5\u00b2Z" + + "\2\u02d3\u02d8\5\u00b0Y\2\u02d4\u02d8\5\u0098M\2\u02d5\u02d8\5J&\2\u02d6" + + "\u02d8\5\u00c4c\2\u02d7\u02d0\3\2\2\2\u02d7\u02d1\3\2\2\2\u02d7\u02d2" + + "\3\2\2\2\u02d7\u02d3\3\2\2\2\u02d7\u02d4\3\2\2\2\u02d7\u02d5\3\2\2\2\u02d7" + + "\u02d6\3\2\2\2\u02d8\u02db\3\2\2\2\u02d9\u02d7\3\2\2\2\u02d9\u02da\3\2" + + "\2\2\u02da\u02dc\3\2\2\2\u02db\u02d9\3\2\2\2\u02dc\u02de\7\5\2\2\u02dd" + + "\u02ce\3\2\2\2\u02dd\u02cf\3\2\2\2\u02deK\3\2\2\2\u02df\u02e0\7\r\2\2" + + "\u02e0\u02e1\5\4\3\2\u02e1\u02e2\5\b\5\2\u02e2M\3\2\2\2\u02e3\u02e4\5" + + "\4\3\2\u02e4O\3\2\2\2\u02e5\u02e6\7)\2\2\u02e6\u02e7\5N(\2\u02e7\u02e8" + + "\5\b\5\2\u02e8Q\3\2\2\2\u02e9\u02ea\7(\2\2\u02ea\u02eb\5\4\3\2\u02eb\u02ec" + + "\5\b\5\2\u02ecS\3\2\2\2\u02ed\u02ee\7<\2\2\u02ee\u02ef\5\4\3\2\u02ef\u02f0" + + "\5\b\5\2\u02f0U\3\2\2\2\u02f1\u02f2\7;\2\2\u02f2\u02f3\5\4\3\2\u02f3\u02f4" + + "\5\b\5\2\u02f4W\3\2\2\2\u02f5\u02f6\7&\2\2\u02f6\u0304\5\4\3\2\u02f7\u0305" + + "\7\3\2\2\u02f8\u0300\7\4\2\2\u02f9\u02ff\5\6\4\2\u02fa\u02ff\5V,\2\u02fb" + + "\u02ff\5T+\2\u02fc\u02ff\5\u00b2Z\2\u02fd\u02ff\5\u00b0Y\2\u02fe\u02f9" + + "\3\2\2\2\u02fe\u02fa\3\2\2\2\u02fe\u02fb\3\2\2\2\u02fe\u02fc\3\2\2\2\u02fe" + + "\u02fd\3\2\2\2\u02ff\u0302\3\2\2\2\u0300\u02fe\3\2\2\2\u0300\u0301\3\2" + + "\2\2\u0301\u0303\3\2\2\2\u0302\u0300\3\2\2\2\u0303\u0305\7\5\2\2\u0304" + + "\u02f7\3\2\2\2\u0304\u02f8\3\2\2\2\u0305Y\3\2\2\2\u0306\u0307\5\4\3\2" + + "\u0307[\3\2\2\2\u0308\u0309\7#\2\2\u0309\u030a\5Z.\2\u030a\u030b\5\b\5" + + "\2\u030b]\3\2\2\2\u030c\u030d\7\34\2\2\u030d\u030e\5\4\3\2\u030e\u030f" + + "\5\b\5\2\u030f_\3\2\2\2\u0310\u0311\5\4\3\2\u0311a\3\2\2\2\u0312\u0313" + + "\7*\2\2\u0313\u0314\5`\61\2\u0314\u0315\5\b\5\2\u0315c\3\2\2\2\u0316\u0317" + + "\5\4\3\2\u0317e\3\2\2\2\u0318\u0319\7B\2\2\u0319\u031a\5d\63\2\u031a\u031b" + + "\5\b\5\2\u031bg\3\2\2\2\u031c\u031d\5\4\3\2\u031di\3\2\2\2\u031e\u031f" + + "\7\24\2\2\u031f\u0320\5h\65\2\u0320\u0321\5\b\5\2\u0321k\3\2\2\2\u0322" + + "\u0323\7\36\2\2\u0323\u0324\5\4\3\2\u0324\u0325\5\b\5\2\u0325m\3\2\2\2" + + "\u0326\u0327\7E\2\2\u0327\u0335\5\4\3\2\u0328\u0336\7\3\2\2\u0329\u0331" + + "\7\4\2\2\u032a\u0330\5\6\4\2\u032b\u0330\5l\67\2\u032c\u0330\5j\66\2\u032d" + + "\u0330\5\u00b2Z\2\u032e\u0330\5\u00b0Y\2\u032f\u032a\3\2\2\2\u032f\u032b" + + "\3\2\2\2\u032f\u032c\3\2\2\2\u032f\u032d\3\2\2\2\u032f\u032e\3\2\2\2\u0330" + + "\u0333\3\2\2\2\u0331\u032f\3\2\2\2\u0331\u0332\3\2\2\2\u0332\u0334\3\2" + + "\2\2\u0333\u0331\3\2\2\2\u0334\u0336\7\5\2\2\u0335\u0328\3\2\2\2\u0335" + + "\u0329\3\2\2\2\u0336o\3\2\2\2\u0337\u0339\5n8\2\u0338\u0337\3\2\2\2\u0339" + + "\u033a\3\2\2\2\u033a\u0338\3\2\2\2\u033a\u033b\3\2\2\2\u033bq\3\2\2\2" + + "\u033c\u033e\5\u0096L\2\u033d\u033c\3\2\2\2\u033e\u033f\3\2\2\2\u033f" + + "\u033d\3\2\2\2\u033f\u0340\3\2\2\2\u0340s\3\2\2\2\u0341\u0342\5\u009e" + + "P\2\u0342u\3\2\2\2\u0343\u0345\5z>\2\u0344\u0343\3\2\2\2\u0344\u0345\3" + + "\2\2\2\u0345w\3\2\2\2\u0346\u0347\5\4\3\2\u0347y\3\2\2\2\u0348\u0349\7" + + "\30\2\2\u0349\u034a\5x=\2\u034a\u034b\5\b\5\2\u034b{\3\2\2\2\u034c\u034d" + + "\7 \2\2\u034d\u034e\5\4\3\2\u034e\u034f\5\b\5\2\u034f}\3\2\2\2\u0350\u0351" + + "\5|?\2\u0351\177\3\2\2\2\u0352\u0353\7=\2\2\u0353\u0361\5\4\3\2\u0354" + + "\u0362\7\3\2\2\u0355\u035d\7\4\2\2\u0356\u035c\5\6\4\2\u0357\u035c\5L" + + "\'\2\u0358\u035c\5j\66\2\u0359\u035c\5\u00b2Z\2\u035a\u035c\5\u00b0Y\2" + + "\u035b\u0356\3\2\2\2\u035b\u0357\3\2\2\2\u035b\u0358\3\2\2\2\u035b\u0359" + + "\3\2\2\2\u035b\u035a\3\2\2\2\u035c\u035f\3\2\2\2\u035d\u035b\3\2\2\2\u035d" + + "\u035e\3\2\2\2\u035e\u0360\3\2\2\2\u035f\u035d\3\2\2\2\u0360\u0362\7\5" + + "\2\2\u0361\u0354\3\2\2\2\u0361\u0355\3\2\2\2\u0362\u0081\3\2\2\2\u0363" + + "\u0365\5\u0080A\2\u0364\u0363\3\2\2\2\u0365\u0366\3\2\2\2\u0366\u0364" + + "\3\2\2\2\u0366\u0367\3\2\2\2\u0367\u0083\3\2\2\2\u0368\u0369\7?\2\2\u0369" + + "\u036a\5\4\3\2\u036a\u036b\5\b\5\2\u036b\u0085\3\2\2\2\u036c\u036d\7\37" + + "\2\2\u036d\u037b\5\4\3\2\u036e\u037c\7\3\2\2\u036f\u0377\7\4\2\2\u0370" + + "\u0376\5\6\4\2\u0371\u0376\5V,\2\u0372\u0376\5T+\2\u0373\u0376\5\u00b2" + + "Z\2\u0374\u0376\5\u00b0Y\2\u0375\u0370\3\2\2\2\u0375\u0371\3\2\2\2\u0375" + + "\u0372\3\2\2\2\u0375\u0373\3\2\2\2\u0375\u0374\3\2\2\2\u0376\u0379\3\2" + + "\2\2\u0377\u0375\3\2\2\2\u0377\u0378\3\2\2\2\u0378\u037a\3\2\2\2\u0379" + + "\u0377\3\2\2\2\u037a\u037c\7\5\2\2\u037b\u036e\3\2\2\2\u037b\u036f\3\2" + + "\2\2\u037c\u0087\3\2\2\2\u037d\u037e\7,\2\2\u037e\u038c\5\4\3\2\u037f" + + "\u038d\7\3\2\2\u0380\u0388\7\4\2\2\u0381\u0387\5\6\4\2\u0382\u0387\5V" + + ",\2\u0383\u0387\5T+\2\u0384\u0387\5\u00b2Z\2\u0385\u0387\5\u00b0Y\2\u0386" + + "\u0381\3\2\2\2\u0386\u0382\3\2\2\2\u0386\u0383\3\2\2\2\u0386\u0384\3\2" + + "\2\2\u0386\u0385\3\2\2\2\u0387\u038a\3\2\2\2\u0388\u0386\3\2\2\2\u0388" + + "\u0389\3\2\2\2\u0389\u038b\3\2\2\2\u038a\u0388\3\2\2\2\u038b\u038d\7\5" + + "\2\2\u038c\u037f\3\2\2\2\u038c\u0380\3\2\2\2\u038d\u0089\3\2\2\2\u038e" + + "\u0391\5\u0088E\2\u038f\u0391\5\u0086D\2\u0390\u038e\3\2\2\2\u0390\u038f" + + "\3\2\2\2\u0391\u0394\3\2\2\2\u0392\u0390\3\2\2\2\u0392\u0393\3\2\2\2\u0393" + + "\u008b\3\2\2\2\u0394\u0392\3\2\2\2\u0395\u0396\7\66\2\2\u0396\u0397\5" + + "\4\3\2\u0397\u0398\5\b\5\2\u0398\u008d\3\2\2\2\u0399\u039b\5\u0092J\2" + + "\u039a\u0399\3\2\2\2\u039a\u039b\3\2\2\2\u039b\u039c\3\2\2\2\u039c\u03a2" + + "\5\u008cG\2\u039d\u039f\5\u008cG\2\u039e\u03a0\5\u0092J\2\u039f\u039e" + + "\3\2\2\2\u039f\u03a0\3\2\2\2\u03a0\u03a2\3\2\2\2\u03a1\u039a\3\2\2\2\u03a1" + + "\u039d\3\2\2\2\u03a2\u008f\3\2\2\2\u03a3\u03a4\7\33\2\2\u03a4\u03b2\5" + + "\4\3\2\u03a5\u03b3\7\3\2\2\u03a6\u03ae\7\4\2\2\u03a7\u03ad\5\6\4\2\u03a8" + + "\u03ad\5V,\2\u03a9\u03ad\5T+\2\u03aa\u03ad\5\u00b2Z\2\u03ab\u03ad\5\u00b0" + + "Y\2\u03ac\u03a7\3\2\2\2\u03ac\u03a8\3\2\2\2\u03ac\u03a9\3\2\2\2\u03ac" + + "\u03aa\3\2\2\2\u03ac\u03ab\3\2\2\2\u03ad\u03b0\3\2\2\2\u03ae\u03ac\3\2" + + "\2\2\u03ae\u03af\3\2\2\2\u03af\u03b1\3\2\2\2\u03b0\u03ae\3\2\2\2\u03b1" + + "\u03b3\7\5\2\2\u03b2\u03a5\3\2\2\2\u03b2\u03a6\3\2\2\2\u03b3\u0091\3\2" + + "\2\2\u03b4\u03b5\5\u0090I\2\u03b5\u0093\3\2\2\2\u03b6\u03c0\5\u0092J\2" + + "\u03b7\u03c0\5\u008eH\2\u03b8\u03c0\5\u008aF\2\u03b9\u03c0\5\u0082B\2" + + "\u03ba\u03c0\5~@\2\u03bb\u03c0\5t;\2\u03bc\u03c0\5v<\2\u03bd\u03c0\5p" + + "9\2\u03be\u03c0\5r:\2\u03bf\u03b6\3\2\2\2\u03bf\u03b7\3\2\2\2\u03bf\u03b8" + + "\3\2\2\2\u03bf\u03b9\3\2\2\2\u03bf\u03ba\3\2\2\2\u03bf\u03bb\3\2\2\2\u03bf" + + "\u03bc\3\2\2\2\u03bf\u03bd\3\2\2\2\u03bf\u03be\3\2\2\2\u03c0\u0095\3\2" + + "\2\2\u03c1\u03c2\7\22\2\2\u03c2\u03c8\5\4\3\2\u03c3\u03c9\7\3\2\2\u03c4" + + "\u03c5\7\4\2\2\u03c5\u03c6\5\u0094K\2\u03c6\u03c7\7\5\2\2\u03c7\u03c9" + + "\3\2\2\2\u03c8\u03c3\3\2\2\2\u03c8\u03c4\3\2\2\2\u03c9\u0097\3\2\2\2\u03ca" + + "\u03cb\7\21\2\2\u03cb\u03cc\5\4\3\2\u03cc\u03d3\7\4\2\2\u03cd\u03d4\5" + + "\u0096L\2\u03ce\u03d4\5\u00aeX\2\u03cf\u03d4\5\u0084C\2\u03d0\u03d4\5" + + "j\66\2\u03d1\u03d4\5\u00b2Z\2\u03d2\u03d4\5\u00b0Y\2\u03d3\u03cd\3\2\2" + + "\2\u03d3\u03ce\3\2\2\2\u03d3\u03cf\3\2\2\2\u03d3\u03d0\3\2\2\2\u03d3\u03d1" + + "\3\2\2\2\u03d3\u03d2\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d5\u03d3\3\2\2\2\u03d5" + + "\u03d6\3\2\2\2\u03d6\u03d7\3\2\2\2\u03d7\u03d8\7\5\2\2\u03d8\u0099\3\2" + + "\2\2\u03d9\u03da\7\63\2\2\u03da\u03db\5\4\3\2\u03db\u03dc\5\b\5\2\u03dc" + + "\u009b\3\2\2\2\u03dd\u03de\7\67\2\2\u03de\u03eb\5\4\3\2\u03df\u03ec\7" + + "\3\2\2\u03e0\u03e7\7\4\2\2\u03e1\u03e6\5\u009aN\2\u03e2\u03e6\5j\66\2" + + "\u03e3\u03e6\5\u00b2Z\2\u03e4\u03e6\5\u00b0Y\2\u03e5\u03e1\3\2\2\2\u03e5" + + "\u03e2\3\2\2\2\u03e5\u03e3\3\2\2\2\u03e5\u03e4\3\2\2\2\u03e6\u03e9\3\2" + + "\2\2\u03e7\u03e5\3\2\2\2\u03e7\u03e8\3\2\2\2\u03e8\u03ea\3\2\2\2\u03e9" + + "\u03e7\3\2\2\2\u03ea\u03ec\7\5\2\2\u03eb\u03df\3\2\2\2\u03eb\u03e0\3\2" + + "\2\2\u03ec\u009d\3\2\2\2\u03ed\u03ee\7G\2\2\u03ee\u03ef\5\4\3\2\u03ef" + + "\u03f0\5\b\5\2\u03f0\u009f\3\2\2\2\u03f1\u03f2\7\64\2\2\u03f2\u03ff\5" + + "\4\3\2\u03f3\u0400\7\3\2\2\u03f4\u03fb\7\4\2\2\u03f5\u03fa\5\u009eP\2" + + "\u03f6\u03fa\5j\66\2\u03f7\u03fa\5\u00b2Z\2\u03f8\u03fa\5\u00b0Y\2\u03f9" + + "\u03f5\3\2\2\2\u03f9\u03f6\3\2\2\2\u03f9\u03f7\3\2\2\2\u03f9\u03f8\3\2" + + "\2\2\u03fa\u03fd\3\2\2\2\u03fb\u03f9\3\2\2\2\u03fb\u03fc\3\2\2\2\u03fc" + + "\u03fe\3\2\2\2\u03fd\u03fb\3\2\2\2\u03fe\u0400\7\5\2\2\u03ff\u03f3\3\2" + + "\2\2\u03ff\u03f4\3\2\2\2\u0400\u00a1\3\2\2\2\u0401\u0402\5\4\3\2\u0402" + + "\u00a3\3\2\2\2\u0403\u0404\7\n\2\2\u0404\u0405\5\u00a2R\2\u0405\u0406" + + "\5\b\5\2\u0406\u00a5\3\2\2\2\u0407\u0408\7I\2\2\u0408\u040f\5\4\3\2\u0409" + + "\u0410\7\3\2\2\u040a\u040c\7\4\2\2\u040b\u040d\5\u00a4S\2\u040c\u040b" + + "\3\2\2\2\u040c\u040d\3\2\2\2\u040d\u040e\3\2\2\2\u040e\u0410\7\5\2\2\u040f" + + "\u0409\3\2\2\2\u040f\u040a\3\2\2\2\u0410\u00a7\3\2\2\2\u0411\u0412\7:" + + "\2\2\u0412\u041f\5\4\3\2\u0413\u0420\7\3\2\2\u0414\u041b\7\4\2\2\u0415" + + "\u041a\5\u00a6T\2\u0416\u041a\5j\66\2\u0417\u041a\5\u00b2Z\2\u0418\u041a" + + "\5\u00b0Y\2\u0419\u0415\3\2\2\2\u0419\u0416\3\2\2\2\u0419\u0417\3\2\2" + + "\2\u0419\u0418\3\2\2\2\u041a\u041d\3\2\2\2\u041b\u0419\3\2\2\2\u041b\u041c" + + "\3\2\2\2\u041c\u041e\3\2\2\2\u041d\u041b\3\2\2\2\u041e\u0420\7\5\2\2\u041f" + + "\u0413\3\2\2\2\u041f\u0414\3\2\2\2\u0420\u00a9\3\2\2\2\u0421\u0422\7\26" + + "\2\2\u0422\u0423\5\4\3\2\u0423\u0424\5\b\5\2\u0424\u00ab\3\2\2\2\u0425" + + "\u0426\7\27\2\2\u0426\u0430\5\4\3\2\u0427\u0431\7\3\2\2\u0428\u042a\7" + + "\4\2\2\u0429\u042b\5\u00b2Z\2\u042a\u0429\3\2\2\2\u042a\u042b\3\2\2\2" + + "\u042b\u042d\3\2\2\2\u042c\u042e\5\u00b0Y\2\u042d\u042c\3\2\2\2\u042d" + + "\u042e\3\2\2\2\u042e\u042f\3\2\2\2\u042f\u0431\7\5\2\2\u0430\u0427\3\2" + + "\2\2\u0430\u0428\3\2\2\2\u0431\u00ad\3\2\2\2\u0432\u0433\7\17\2\2\u0433" + + "\u0434\5\4\3\2\u0434\u0435\5\b\5\2\u0435\u00af\3\2\2\2\u0436\u0437\7\32" + + "\2\2\u0437\u0438\5\4\3\2\u0438\u0439\5\b\5\2\u0439\u00b1\3\2\2\2\u043a" + + "\u043b\7>\2\2\u043b\u043c\5\4\3\2\u043c\u043d\5\b\5\2\u043d\u00b3\3\2" + + "\2\2\u043e\u043f\7A\2\2\u043f\u0440\5\4\3\2\u0440\u0441\5\b\5\2\u0441" + + "\u00b5\3\2\2\2\u0442\u0443\7\"\2\2\u0443\u0444\5\4\3\2\u0444\u0445\5\b" + + "\5\2\u0445\u00b7\3\2\2\2\u0446\u0447\7F\2\2\u0447\u0448\5\4\3\2\u0448" + + "\u0449\7\4\2\2\u0449\u044a\5\u00ba^\2\u044a\u044b\7\5\2\2\u044b\u00b9" + + "\3\2\2\2\u044c\u044d\7\35\2\2\u044d\u044e\5\4\3\2\u044e\u044f\5\b\5\2" + + "\u044f\u00bb\3\2\2\2\u0450\u0451\7%\2\2\u0451\u0452\5\4\3\2\u0452\u0453" + + "\5\b\5\2\u0453\u00bd\3\2\2\2\u0454\u0455\7\61\2\2\u0455\u045c\5\4\3\2" + + "\u0456\u045d\7\3\2\2\u0457\u0459\7\4\2\2\u0458\u045a\5\u00aaV\2\u0459" + + "\u0458\3\2\2\2\u0459\u045a\3\2\2\2\u045a\u045b\3\2\2\2\u045b\u045d\7\5" + + "\2\2\u045c\u0456\3\2\2\2\u045c\u0457\3\2\2\2\u045d\u00bf\3\2\2\2\u045e" + + "\u045f\7\62\2\2\u045f\u0460\5\4\3\2\u0460\u0461\7\4\2\2\u0461\u0463\5" + + "\u00ba^\2\u0462\u0464\5\u00aaV\2\u0463\u0462\3\2\2\2\u0463\u0464\3\2\2" + + "\2\u0464\u0465\3\2\2\2\u0465\u0466\7\5\2\2\u0466\u00c1\3\2\2\2\u0467\u0468" + + "\7\13\2\2\u0468\u0469\5\4\3\2\u0469\u046a\5\b\5\2\u046a\u00c3\3\2\2\2" + + "\u046b\u0473\5H%\2\u046c\u0473\5F$\2\u046d\u0473\5D#\2\u046e\u0473\5B" + + "\"\2\u046f\u0473\5<\37\2\u0470\u0473\5\66\34\2\u0471\u0473\5\64\33\2\u0472" + + "\u046b\3\2\2\2\u0472\u046c\3\2\2\2\u0472\u046d\3\2\2\2\u0472\u046e\3\2" + + "\2\2\u0472\u046f\3\2\2\2\u0472\u0470\3\2\2\2\u0472\u0471\3\2\2\2\u0473" + + "\u00c5\3\2\2\2\u0474\u047f\5\u00a8U\2\u0475\u047f\5\u009cO\2\u0476\u047f" + + "\5\u00a0Q\2\u0477\u047f\5\u0098M\2\u0478\u047f\5J&\2\u0479\u047f\5\u00c4" + + "c\2\u047a\u047f\5\36\20\2\u047b\u047f\5\32\16\2\u047c\u047f\5\24\13\2" + + "\u047d\u047f\5\22\n\2\u047e\u0474\3\2\2\2\u047e\u0475\3\2\2\2\u047e\u0476" + + "\3\2\2\2\u047e\u0477\3\2\2\2\u047e\u0478\3\2\2\2\u047e\u0479\3\2\2\2\u047e" + + "\u047a\3\2\2\2\u047e\u047b\3\2\2\2\u047e\u047c\3\2\2\2\u047e\u047d\3\2" + + "\2\2\u047f\u0481\3\2\2\2\u0480\u047e\3\2\2\2\u0481\u0484\3\2\2\2\u0482" + + "\u0480\3\2\2\2\u0482\u0483\3\2\2\2\u0483\u00c7\3\2\2\2\u0484\u0482\3\2" + + "\2\2\u0485\u0487\5\u00acW\2\u0486\u0485\3\2\2\2\u0487\u048a\3\2\2\2\u0488" + + "\u0486\3\2\2\2\u0488\u0489\3\2\2\2\u0489\u00c9\3\2\2\2\u048a\u0488\3\2" + + "\2\2\u048b\u048e\5\u00c0a\2\u048c\u048e\5\u00be`\2\u048d\u048b\3\2\2\2" + + "\u048d\u048c\3\2\2\2\u048e\u0491\3\2\2\2\u048f\u048d\3\2\2\2\u048f\u0490" + + "\3\2\2\2\u0490\u00cb\3\2\2\2\u0491\u048f\3\2\2\2\u0492\u0497\5\u00b6\\" + + "\2\u0493\u0497\5\u00b4[\2\u0494\u0497\5\u00b2Z\2\u0495\u0497\5\u00b0Y" + + "\2\u0496\u0492\3\2\2\2\u0496\u0493\3\2\2\2\u0496\u0494\3\2\2\2\u0496\u0495" + + "\3\2\2\2\u0497\u049a\3\2\2\2\u0498\u0496\3\2\2\2\u0498\u0499\3\2\2\2\u0499" + + "\u00cd\3\2\2\2\u049a\u0498\3\2\2\2\u049b\u049e\5\u00c2b\2\u049c\u049e" + + "\5\u00b8]\2\u049d\u049b\3\2\2\2\u049d\u049c\3\2\2\2\u049e\u049f\3\2\2" + + "\2\u049f\u049d\3\2\2\2\u049f\u04a0\3\2\2\2\u04a0\u00cf\3\2\2\2\u04a1\u04a5" + + "\5\u00c2b\2\u04a2\u04a5\5\u00bc_\2\u04a3\u04a5\5\u00ba^\2\u04a4\u04a1" + + "\3\2\2\2\u04a4\u04a2\3\2\2\2\u04a4\u04a3\3\2\2\2\u04a5\u04a6\3\2\2\2\u04a6" + + "\u04a4\3\2\2\2\u04a6\u04a7\3\2\2\2\u04a7\u00d1\3\2\2\2\u04a8\u04a9\7\23" + + "\2\2\u04a9\u04aa\5\4\3\2\u04aa\u04ab\7\4\2\2\u04ab\u04ac\5\u00ceh\2\u04ac" + + "\u04ad\5\u00caf\2\u04ad\u04ae\5\u00ccg\2\u04ae\u04af\5\u00c8e\2\u04af" + + "\u04b0\5\u00c6d\2\u04b0\u04b1\7\5\2\2\u04b1\u00d3\3\2\2\2\u04b2\u04b3" + + "\7\'\2\2\u04b3\u04b4\5\4\3\2\u04b4\u04b5\7\4\2\2\u04b5\u04b6\5\u00d0i" + + "\2\u04b6\u04b7\5\u00caf\2\u04b7\u04b8\5\u00ccg\2\u04b8\u04b9\5\u00c8e" + + "\2\u04b9\u04ba\5\u00c6d\2\u04ba\u04bb\7\5\2\2\u04bb\u00d5\3\2\2\2\u008c" + + "\u00d8\u00df\u00e4\u00ea\u00ee\u00f1\u00fe\u0100\u0104\u010e\u0110\u0114" + + "\u0122\u0124\u0128\u012f\u0132\u013d\u013f\u014e\u0150\u0154\u015b\u015d" + + "\u0166\u0168\u0178\u017a\u017e\u0186\u0188\u018c\u0199\u019b\u01aa\u01ac" + + "\u01b5\u01b7\u01bc\u01be\u01c6\u01c8\u01d1\u01d3\u01dc\u01de\u01e7\u01e9" + + "\u01f1\u01f3\u01fd\u0206\u020a\u0218\u021a\u021e\u022d\u022f\u0233\u0240" + + "\u0242\u0246\u024d\u025e\u0260\u0264\u0281\u0283\u0297\u0299\u02ad\u02af" + + "\u02c4\u02c6\u02ca\u02d7\u02d9\u02dd\u02fe\u0300\u0304\u032f\u0331\u0335" + + "\u033a\u033f\u0344\u035b\u035d\u0361\u0366\u0375\u0377\u037b\u0386\u0388" + + "\u038c\u0390\u0392\u039a\u039f\u03a1\u03ac\u03ae\u03b2\u03bf\u03c8\u03d3" + + "\u03d5\u03e5\u03e7\u03eb\u03f9\u03fb\u03ff\u040c\u040f\u0419\u041b\u041f" + + "\u042a\u042d\u0430\u0459\u045c\u0463\u0472\u047e\u0482\u0488\u048d\u048f" + + "\u0496\u0498\u049d\u049f\u04a4\u04a6"; + public static final ATN _ATN = ATNSimulator.deserialize(_serializedATN + .toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserBaseListener.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserBaseListener.java new file mode 100644 index 0000000000..524201afe3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserBaseListener.java @@ -0,0 +1,916 @@ +/* + * 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.controller.antlrv4.code.gen; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +public class YangParserBaseListener implements YangParserListener { + @Override + public void enterEnum_specification(YangParser.Enum_specificationContext ctx) { + } + + @Override + public void exitEnum_specification(YangParser.Enum_specificationContext ctx) { + } + + @Override + public void enterRefine_leaf_list_stmts( + YangParser.Refine_leaf_list_stmtsContext ctx) { + } + + @Override + public void exitRefine_leaf_list_stmts( + YangParser.Refine_leaf_list_stmtsContext ctx) { + } + + @Override + public void enterPosition_stmt(YangParser.Position_stmtContext ctx) { + } + + @Override + public void exitPosition_stmt(YangParser.Position_stmtContext ctx) { + } + + @Override + public void enterArgument_stmt(YangParser.Argument_stmtContext ctx) { + } + + @Override + public void exitArgument_stmt(YangParser.Argument_stmtContext ctx) { + } + + @Override + public void enterLeafref_specification( + YangParser.Leafref_specificationContext ctx) { + } + + @Override + public void exitLeafref_specification( + YangParser.Leafref_specificationContext ctx) { + } + + @Override + public void enterError_app_tag_stmt(YangParser.Error_app_tag_stmtContext ctx) { + } + + @Override + public void exitError_app_tag_stmt(YangParser.Error_app_tag_stmtContext ctx) { + } + + @Override + public void enterData_def_stmt(YangParser.Data_def_stmtContext ctx) { + } + + @Override + public void exitData_def_stmt(YangParser.Data_def_stmtContext ctx) { + } + + @Override + public void enterIdentity_stmt(YangParser.Identity_stmtContext ctx) { + } + + @Override + public void exitIdentity_stmt(YangParser.Identity_stmtContext ctx) { + } + + @Override + public void enterDeviate_not_supported_stmt( + YangParser.Deviate_not_supported_stmtContext ctx) { + } + + @Override + public void exitDeviate_not_supported_stmt( + YangParser.Deviate_not_supported_stmtContext ctx) { + } + + @Override + public void enterPrefix_stmt(YangParser.Prefix_stmtContext ctx) { + } + + @Override + public void exitPrefix_stmt(YangParser.Prefix_stmtContext ctx) { + } + + @Override + public void enterMeta_stmts(YangParser.Meta_stmtsContext ctx) { + } + + @Override + public void exitMeta_stmts(YangParser.Meta_stmtsContext ctx) { + } + + @Override + public void enterLinkage_stmts(YangParser.Linkage_stmtsContext ctx) { + } + + @Override + public void exitLinkage_stmts(YangParser.Linkage_stmtsContext ctx) { + } + + @Override + public void enterGrouping_stmt(YangParser.Grouping_stmtContext ctx) { + } + + @Override + public void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx) { + } + + @Override + public void enterFeature_stmt(YangParser.Feature_stmtContext ctx) { + } + + @Override + public void exitFeature_stmt(YangParser.Feature_stmtContext ctx) { + } + + @Override + public void enterYang(YangParser.YangContext ctx) { + } + + @Override + public void exitYang(YangParser.YangContext ctx) { + } + + @Override + public void enterIdentityref_specification( + YangParser.Identityref_specificationContext ctx) { + } + + @Override + public void exitIdentityref_specification( + YangParser.Identityref_specificationContext ctx) { + } + + @Override + public void enterNumerical_restrictions( + YangParser.Numerical_restrictionsContext ctx) { + } + + @Override + public void exitNumerical_restrictions( + YangParser.Numerical_restrictionsContext ctx) { + } + + @Override + public void enterModule_header_stmts( + YangParser.Module_header_stmtsContext ctx) { + } + + @Override + public void exitModule_header_stmts( + YangParser.Module_header_stmtsContext ctx) { + } + + @Override + public void enterRequire_instance_stmt( + YangParser.Require_instance_stmtContext ctx) { + } + + @Override + public void exitRequire_instance_stmt( + YangParser.Require_instance_stmtContext ctx) { + } + + @Override + public void enterBit_stmt(YangParser.Bit_stmtContext ctx) { + } + + @Override + public void exitBit_stmt(YangParser.Bit_stmtContext ctx) { + } + + @Override + public void enterType_stmt(YangParser.Type_stmtContext ctx) { + } + + @Override + public void exitType_stmt(YangParser.Type_stmtContext ctx) { + } + + @Override + public void enterPattern_stmt(YangParser.Pattern_stmtContext ctx) { + } + + @Override + public void exitPattern_stmt(YangParser.Pattern_stmtContext ctx) { + } + + @Override + public void enterDeviation_stmt(YangParser.Deviation_stmtContext ctx) { + } + + @Override + public void exitDeviation_stmt(YangParser.Deviation_stmtContext ctx) { + } + + @Override + public void enterDeviate_replace_stmt( + YangParser.Deviate_replace_stmtContext ctx) { + } + + @Override + public void exitDeviate_replace_stmt( + YangParser.Deviate_replace_stmtContext ctx) { + } + + @Override + public void enterKey_stmt(YangParser.Key_stmtContext ctx) { + } + + @Override + public void exitKey_stmt(YangParser.Key_stmtContext ctx) { + } + + @Override + public void enterRequire_instance_arg( + YangParser.Require_instance_argContext ctx) { + } + + @Override + public void exitRequire_instance_arg( + YangParser.Require_instance_argContext ctx) { + } + + @Override + public void enterLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) { + } + + @Override + public void exitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) { + } + + @Override + public void enterAugment_stmt(YangParser.Augment_stmtContext ctx) { + } + + @Override + public void exitAugment_stmt(YangParser.Augment_stmtContext ctx) { + } + + @Override + public void enterDeviate_delete_stmt( + YangParser.Deviate_delete_stmtContext ctx) { + } + + @Override + public void exitDeviate_delete_stmt( + YangParser.Deviate_delete_stmtContext ctx) { + } + + @Override + public void enterTypedef_stmt(YangParser.Typedef_stmtContext ctx) { + } + + @Override + public void exitTypedef_stmt(YangParser.Typedef_stmtContext ctx) { + } + + @Override + public void enterContainer_stmt(YangParser.Container_stmtContext ctx) { + } + + @Override + public void exitContainer_stmt(YangParser.Container_stmtContext ctx) { + } + + @Override + public void enterBelongs_to_stmt(YangParser.Belongs_to_stmtContext ctx) { + } + + @Override + public void exitBelongs_to_stmt(YangParser.Belongs_to_stmtContext ctx) { + } + + @Override + public void enterBase_stmt(YangParser.Base_stmtContext ctx) { + } + + @Override + public void exitBase_stmt(YangParser.Base_stmtContext ctx) { + } + + @Override + public void enterYang_version_stmt(YangParser.Yang_version_stmtContext ctx) { + } + + @Override + public void exitYang_version_stmt(YangParser.Yang_version_stmtContext ctx) { + } + + @Override + public void enterReference_stmt(YangParser.Reference_stmtContext ctx) { + } + + @Override + public void exitReference_stmt(YangParser.Reference_stmtContext ctx) { + } + + @Override + public void enterYin_element_stmt(YangParser.Yin_element_stmtContext ctx) { + } + + @Override + public void exitYin_element_stmt(YangParser.Yin_element_stmtContext ctx) { + } + + @Override + public void enterLeaf_stmt(YangParser.Leaf_stmtContext ctx) { + } + + @Override + public void exitLeaf_stmt(YangParser.Leaf_stmtContext ctx) { + } + + @Override + public void enterCase_stmt(YangParser.Case_stmtContext ctx) { + } + + @Override + public void exitCase_stmt(YangParser.Case_stmtContext ctx) { + } + + @Override + public void enterModule_stmt(YangParser.Module_stmtContext ctx) { + } + + @Override + public void exitModule_stmt(YangParser.Module_stmtContext ctx) { + } + + @Override + public void enterRpc_stmt(YangParser.Rpc_stmtContext ctx) { + } + + @Override + public void exitRpc_stmt(YangParser.Rpc_stmtContext ctx) { + } + + @Override + public void enterType_body_stmts(YangParser.Type_body_stmtsContext ctx) { + } + + @Override + public void exitType_body_stmts(YangParser.Type_body_stmtsContext ctx) { + } + + @Override + public void enterExtension_stmt(YangParser.Extension_stmtContext ctx) { + } + + @Override + public void exitExtension_stmt(YangParser.Extension_stmtContext ctx) { + } + + @Override + public void enterSubmodule_header_stmts( + YangParser.Submodule_header_stmtsContext ctx) { + } + + @Override + public void exitSubmodule_header_stmts( + YangParser.Submodule_header_stmtsContext ctx) { + } + + @Override + public void enterRefine_container_stmts( + YangParser.Refine_container_stmtsContext ctx) { + } + + @Override + public void exitRefine_container_stmts( + YangParser.Refine_container_stmtsContext ctx) { + } + + @Override + public void enterValue_stmt(YangParser.Value_stmtContext ctx) { + } + + @Override + public void exitValue_stmt(YangParser.Value_stmtContext ctx) { + } + + @Override + public void enterRefine_list_stmts(YangParser.Refine_list_stmtsContext ctx) { + } + + @Override + public void exitRefine_list_stmts(YangParser.Refine_list_stmtsContext ctx) { + } + + @Override + public void enterDefault_stmt(YangParser.Default_stmtContext ctx) { + } + + @Override + public void exitDefault_stmt(YangParser.Default_stmtContext ctx) { + } + + @Override + public void enterRevision_stmts(YangParser.Revision_stmtsContext ctx) { + } + + @Override + public void exitRevision_stmts(YangParser.Revision_stmtsContext ctx) { + } + + @Override + public void enterAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) { + } + + @Override + public void exitAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) { + } + + @Override + public void enterStatus_stmt(YangParser.Status_stmtContext ctx) { + } + + @Override + public void exitStatus_stmt(YangParser.Status_stmtContext ctx) { + } + + @Override + public void enterContact_stmt(YangParser.Contact_stmtContext ctx) { + } + + @Override + public void exitContact_stmt(YangParser.Contact_stmtContext ctx) { + } + + @Override + public void enterIdentifier_stmt(YangParser.Identifier_stmtContext ctx) { + } + + @Override + public void exitIdentifier_stmt(YangParser.Identifier_stmtContext ctx) { + } + + @Override + public void enterString(YangParser.StringContext ctx) { + } + + @Override + public void exitString(YangParser.StringContext ctx) { + } + + @Override + public void enterRefine_choice_stmts( + YangParser.Refine_choice_stmtsContext ctx) { + } + + @Override + public void exitRefine_choice_stmts( + YangParser.Refine_choice_stmtsContext ctx) { + } + + @Override + public void enterMandatory_arg(YangParser.Mandatory_argContext ctx) { + } + + @Override + public void exitMandatory_arg(YangParser.Mandatory_argContext ctx) { + } + + @Override + public void enterRefine_stmt(YangParser.Refine_stmtContext ctx) { + } + + @Override + public void exitRefine_stmt(YangParser.Refine_stmtContext ctx) { + } + + @Override + public void enterInstance_identifier_specification( + YangParser.Instance_identifier_specificationContext ctx) { + } + + @Override + public void exitInstance_identifier_specification( + YangParser.Instance_identifier_specificationContext ctx) { + } + + @Override + public void enterBits_specification(YangParser.Bits_specificationContext ctx) { + } + + @Override + public void exitBits_specification(YangParser.Bits_specificationContext ctx) { + } + + @Override + public void enterWhen_stmt(YangParser.When_stmtContext ctx) { + } + + @Override + public void exitWhen_stmt(YangParser.When_stmtContext ctx) { + } + + @Override + public void enterString_restrictions( + YangParser.String_restrictionsContext ctx) { + } + + @Override + public void exitString_restrictions( + YangParser.String_restrictionsContext ctx) { + } + + @Override + public void enterRefine_leaf_stmts(YangParser.Refine_leaf_stmtsContext ctx) { + } + + @Override + public void exitRefine_leaf_stmts(YangParser.Refine_leaf_stmtsContext ctx) { + } + + @Override + public void enterMandatory_stmt(YangParser.Mandatory_stmtContext ctx) { + } + + @Override + public void exitMandatory_stmt(YangParser.Mandatory_stmtContext ctx) { + } + + @Override + public void enterOrdered_by_arg(YangParser.Ordered_by_argContext ctx) { + } + + @Override + public void exitOrdered_by_arg(YangParser.Ordered_by_argContext ctx) { + } + + @Override + public void enterMin_elements_stmt(YangParser.Min_elements_stmtContext ctx) { + } + + @Override + public void exitMin_elements_stmt(YangParser.Min_elements_stmtContext ctx) { + } + + @Override + public void enterStmtend(YangParser.StmtendContext ctx) { + } + + @Override + public void exitStmtend(YangParser.StmtendContext ctx) { + } + + @Override + public void enterRefine_anyxml_stmts( + YangParser.Refine_anyxml_stmtsContext ctx) { + } + + @Override + public void exitRefine_anyxml_stmts( + YangParser.Refine_anyxml_stmtsContext ctx) { + } + + @Override + public void enterDescription_stmt(YangParser.Description_stmtContext ctx) { + } + + @Override + public void exitDescription_stmt(YangParser.Description_stmtContext ctx) { + } + + @Override + public void enterPath_stmt(YangParser.Path_stmtContext ctx) { + } + + @Override + public void exitPath_stmt(YangParser.Path_stmtContext ctx) { + } + + @Override + public void enterInclude_stmt(YangParser.Include_stmtContext ctx) { + } + + @Override + public void exitInclude_stmt(YangParser.Include_stmtContext ctx) { + } + + @Override + public void enterUnits_stmt(YangParser.Units_stmtContext ctx) { + } + + @Override + public void exitUnits_stmt(YangParser.Units_stmtContext ctx) { + } + + @Override + public void enterUses_stmt(YangParser.Uses_stmtContext ctx) { + } + + @Override + public void exitUses_stmt(YangParser.Uses_stmtContext ctx) { + } + + @Override + public void enterOrdered_by_stmt(YangParser.Ordered_by_stmtContext ctx) { + } + + @Override + public void exitOrdered_by_stmt(YangParser.Ordered_by_stmtContext ctx) { + } + + @Override + public void enterRange_stmt(YangParser.Range_stmtContext ctx) { + } + + @Override + public void exitRange_stmt(YangParser.Range_stmtContext ctx) { + } + + @Override + public void enterNamespace_stmt(YangParser.Namespace_stmtContext ctx) { + } + + @Override + public void exitNamespace_stmt(YangParser.Namespace_stmtContext ctx) { + } + + @Override + public void enterDeviate_add_stmt(YangParser.Deviate_add_stmtContext ctx) { + } + + @Override + public void exitDeviate_add_stmt(YangParser.Deviate_add_stmtContext ctx) { + } + + @Override + public void enterShort_case_stmt(YangParser.Short_case_stmtContext ctx) { + } + + @Override + public void exitShort_case_stmt(YangParser.Short_case_stmtContext ctx) { + } + + @Override + public void enterConfig_stmt(YangParser.Config_stmtContext ctx) { + } + + @Override + public void exitConfig_stmt(YangParser.Config_stmtContext ctx) { + } + + @Override + public void enterEnum_stmt(YangParser.Enum_stmtContext ctx) { + } + + @Override + public void exitEnum_stmt(YangParser.Enum_stmtContext ctx) { + } + + @Override + public void enterYin_element_arg(YangParser.Yin_element_argContext ctx) { + } + + @Override + public void exitYin_element_arg(YangParser.Yin_element_argContext ctx) { + } + + @Override + public void enterOrganization_stmt(YangParser.Organization_stmtContext ctx) { + } + + @Override + public void exitOrganization_stmt(YangParser.Organization_stmtContext ctx) { + } + + @Override + public void enterUnion_specification( + YangParser.Union_specificationContext ctx) { + } + + @Override + public void exitUnion_specification( + YangParser.Union_specificationContext ctx) { + } + + @Override + public void enterMax_value_arg(YangParser.Max_value_argContext ctx) { + } + + @Override + public void exitMax_value_arg(YangParser.Max_value_argContext ctx) { + } + + @Override + public void enterSubmodule_stmt(YangParser.Submodule_stmtContext ctx) { + } + + @Override + public void exitSubmodule_stmt(YangParser.Submodule_stmtContext ctx) { + } + + @Override + public void enterStatus_arg(YangParser.Status_argContext ctx) { + } + + @Override + public void exitStatus_arg(YangParser.Status_argContext ctx) { + } + + @Override + public void enterList_stmt(YangParser.List_stmtContext ctx) { + } + + @Override + public void exitList_stmt(YangParser.List_stmtContext ctx) { + } + + @Override + public void enterMax_elements_stmt(YangParser.Max_elements_stmtContext ctx) { + } + + @Override + public void exitMax_elements_stmt(YangParser.Max_elements_stmtContext ctx) { + } + + @Override + public void enterImport_stmt(YangParser.Import_stmtContext ctx) { + } + + @Override + public void exitImport_stmt(YangParser.Import_stmtContext ctx) { + } + + @Override + public void enterConfig_arg(YangParser.Config_argContext ctx) { + } + + @Override + public void exitConfig_arg(YangParser.Config_argContext ctx) { + } + + @Override + public void enterRevision_date_stmt(YangParser.Revision_date_stmtContext ctx) { + } + + @Override + public void exitRevision_date_stmt(YangParser.Revision_date_stmtContext ctx) { + } + + @Override + public void enterRefune_pom(YangParser.Refune_pomContext ctx) { + } + + @Override + public void exitRefune_pom(YangParser.Refune_pomContext ctx) { + } + + @Override + public void enterPresence_stmt(YangParser.Presence_stmtContext ctx) { + } + + @Override + public void exitPresence_stmt(YangParser.Presence_stmtContext ctx) { + } + + @Override + public void enterFraction_digits_stmt( + YangParser.Fraction_digits_stmtContext ctx) { + } + + @Override + public void exitFraction_digits_stmt( + YangParser.Fraction_digits_stmtContext ctx) { + } + + @Override + public void enterNotification_stmt(YangParser.Notification_stmtContext ctx) { + } + + @Override + public void exitNotification_stmt(YangParser.Notification_stmtContext ctx) { + } + + @Override + public void enterInput_stmt(YangParser.Input_stmtContext ctx) { + } + + @Override + public void exitInput_stmt(YangParser.Input_stmtContext ctx) { + } + + @Override + public void enterUses_augment_stmt(YangParser.Uses_augment_stmtContext ctx) { + } + + @Override + public void exitUses_augment_stmt(YangParser.Uses_augment_stmtContext ctx) { + } + + @Override + public void enterRefine_case_stmts(YangParser.Refine_case_stmtsContext ctx) { + } + + @Override + public void exitRefine_case_stmts(YangParser.Refine_case_stmtsContext ctx) { + } + + @Override + public void enterDecimal64_specification( + YangParser.Decimal64_specificationContext ctx) { + } + + @Override + public void exitDecimal64_specification( + YangParser.Decimal64_specificationContext ctx) { + } + + @Override + public void enterIf_feature_stmt(YangParser.If_feature_stmtContext ctx) { + } + + @Override + public void exitIf_feature_stmt(YangParser.If_feature_stmtContext ctx) { + } + + @Override + public void enterRevision_stmt(YangParser.Revision_stmtContext ctx) { + } + + @Override + public void exitRevision_stmt(YangParser.Revision_stmtContext ctx) { + } + + @Override + public void enterLength_stmt(YangParser.Length_stmtContext ctx) { + } + + @Override + public void exitLength_stmt(YangParser.Length_stmtContext ctx) { + } + + @Override + public void enterMust_stmt(YangParser.Must_stmtContext ctx) { + } + + @Override + public void exitMust_stmt(YangParser.Must_stmtContext ctx) { + } + + @Override + public void enterBody_stmts(YangParser.Body_stmtsContext ctx) { + } + + @Override + public void exitBody_stmts(YangParser.Body_stmtsContext ctx) { + } + + @Override + public void enterError_message_stmt(YangParser.Error_message_stmtContext ctx) { + } + + @Override + public void exitError_message_stmt(YangParser.Error_message_stmtContext ctx) { + } + + @Override + public void enterUnique_stmt(YangParser.Unique_stmtContext ctx) { + } + + @Override + public void exitUnique_stmt(YangParser.Unique_stmtContext ctx) { + } + + @Override + public void enterChoice_stmt(YangParser.Choice_stmtContext ctx) { + } + + @Override + public void exitChoice_stmt(YangParser.Choice_stmtContext ctx) { + } + + @Override + public void enterOutput_stmt(YangParser.Output_stmtContext ctx) { + } + + @Override + public void exitOutput_stmt(YangParser.Output_stmtContext ctx) { + } + + @Override + public void enterEveryRule(ParserRuleContext ctx) { + } + + @Override + public void exitEveryRule(ParserRuleContext ctx) { + } + + @Override + public void visitTerminal(TerminalNode node) { + } + + @Override + public void visitErrorNode(ErrorNode node) { + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserBaseVisitor.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserBaseVisitor.java new file mode 100644 index 0000000000..4839edb038 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserBaseVisitor.java @@ -0,0 +1,556 @@ +/* + * 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.controller.antlrv4.code.gen; + +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +public class YangParserBaseVisitor extends AbstractParseTreeVisitor + implements YangParserVisitor { + @Override + public T visitEnum_specification(YangParser.Enum_specificationContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefine_leaf_list_stmts( + YangParser.Refine_leaf_list_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitPosition_stmt(YangParser.Position_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitArgument_stmt(YangParser.Argument_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitLeafref_specification( + YangParser.Leafref_specificationContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitError_app_tag_stmt(YangParser.Error_app_tag_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitData_def_stmt(YangParser.Data_def_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitIdentity_stmt(YangParser.Identity_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitDeviate_not_supported_stmt( + YangParser.Deviate_not_supported_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitPrefix_stmt(YangParser.Prefix_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitMeta_stmts(YangParser.Meta_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitLinkage_stmts(YangParser.Linkage_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitGrouping_stmt(YangParser.Grouping_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitFeature_stmt(YangParser.Feature_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitYang(YangParser.YangContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitIdentityref_specification( + YangParser.Identityref_specificationContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitNumerical_restrictions( + YangParser.Numerical_restrictionsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitModule_header_stmts(YangParser.Module_header_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRequire_instance_stmt( + YangParser.Require_instance_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitBit_stmt(YangParser.Bit_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitType_stmt(YangParser.Type_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitPattern_stmt(YangParser.Pattern_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitDeviation_stmt(YangParser.Deviation_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitDeviate_replace_stmt( + YangParser.Deviate_replace_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitKey_stmt(YangParser.Key_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRequire_instance_arg( + YangParser.Require_instance_argContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitAugment_stmt(YangParser.Augment_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitDeviate_delete_stmt(YangParser.Deviate_delete_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitTypedef_stmt(YangParser.Typedef_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitContainer_stmt(YangParser.Container_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitBelongs_to_stmt(YangParser.Belongs_to_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitBase_stmt(YangParser.Base_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitYang_version_stmt(YangParser.Yang_version_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitReference_stmt(YangParser.Reference_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitYin_element_stmt(YangParser.Yin_element_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitLeaf_stmt(YangParser.Leaf_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitCase_stmt(YangParser.Case_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitModule_stmt(YangParser.Module_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRpc_stmt(YangParser.Rpc_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitType_body_stmts(YangParser.Type_body_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitExtension_stmt(YangParser.Extension_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitSubmodule_header_stmts( + YangParser.Submodule_header_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefine_container_stmts( + YangParser.Refine_container_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitValue_stmt(YangParser.Value_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefine_list_stmts(YangParser.Refine_list_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitDefault_stmt(YangParser.Default_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRevision_stmts(YangParser.Revision_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitStatus_stmt(YangParser.Status_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitContact_stmt(YangParser.Contact_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitIdentifier_stmt(YangParser.Identifier_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitString(YangParser.StringContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefine_choice_stmts(YangParser.Refine_choice_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitMandatory_arg(YangParser.Mandatory_argContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefine_stmt(YangParser.Refine_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitInstance_identifier_specification( + YangParser.Instance_identifier_specificationContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitBits_specification(YangParser.Bits_specificationContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitWhen_stmt(YangParser.When_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitString_restrictions(YangParser.String_restrictionsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefine_leaf_stmts(YangParser.Refine_leaf_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitMandatory_stmt(YangParser.Mandatory_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitOrdered_by_arg(YangParser.Ordered_by_argContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitMin_elements_stmt(YangParser.Min_elements_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitStmtend(YangParser.StmtendContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefine_anyxml_stmts(YangParser.Refine_anyxml_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitDescription_stmt(YangParser.Description_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitPath_stmt(YangParser.Path_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitInclude_stmt(YangParser.Include_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitUnits_stmt(YangParser.Units_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitUses_stmt(YangParser.Uses_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitOrdered_by_stmt(YangParser.Ordered_by_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRange_stmt(YangParser.Range_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitNamespace_stmt(YangParser.Namespace_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitDeviate_add_stmt(YangParser.Deviate_add_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitShort_case_stmt(YangParser.Short_case_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitConfig_stmt(YangParser.Config_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitEnum_stmt(YangParser.Enum_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitYin_element_arg(YangParser.Yin_element_argContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitOrganization_stmt(YangParser.Organization_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitUnion_specification(YangParser.Union_specificationContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitMax_value_arg(YangParser.Max_value_argContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitSubmodule_stmt(YangParser.Submodule_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitStatus_arg(YangParser.Status_argContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitList_stmt(YangParser.List_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitMax_elements_stmt(YangParser.Max_elements_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitImport_stmt(YangParser.Import_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitConfig_arg(YangParser.Config_argContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRevision_date_stmt(YangParser.Revision_date_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefune_pom(YangParser.Refune_pomContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitPresence_stmt(YangParser.Presence_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitFraction_digits_stmt( + YangParser.Fraction_digits_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitNotification_stmt(YangParser.Notification_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitInput_stmt(YangParser.Input_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitUses_augment_stmt(YangParser.Uses_augment_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRefine_case_stmts(YangParser.Refine_case_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitDecimal64_specification( + YangParser.Decimal64_specificationContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitIf_feature_stmt(YangParser.If_feature_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitRevision_stmt(YangParser.Revision_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitLength_stmt(YangParser.Length_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitMust_stmt(YangParser.Must_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitBody_stmts(YangParser.Body_stmtsContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitError_message_stmt(YangParser.Error_message_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitUnique_stmt(YangParser.Unique_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitChoice_stmt(YangParser.Choice_stmtContext ctx) { + return visitChildren(ctx); + } + + @Override + public T visitOutput_stmt(YangParser.Output_stmtContext ctx) { + return visitChildren(ctx); + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserListener.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserListener.java new file mode 100644 index 0000000000..09734aeede --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserListener.java @@ -0,0 +1,448 @@ +/* + * 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.controller.antlrv4.code.gen; + +import org.antlr.v4.runtime.tree.ParseTreeListener; + +public interface YangParserListener extends ParseTreeListener { + void enterEnum_specification(YangParser.Enum_specificationContext ctx); + + void exitEnum_specification(YangParser.Enum_specificationContext ctx); + + void enterRefine_leaf_list_stmts( + YangParser.Refine_leaf_list_stmtsContext ctx); + + void exitRefine_leaf_list_stmts(YangParser.Refine_leaf_list_stmtsContext ctx); + + void enterPosition_stmt(YangParser.Position_stmtContext ctx); + + void exitPosition_stmt(YangParser.Position_stmtContext ctx); + + void enterArgument_stmt(YangParser.Argument_stmtContext ctx); + + void exitArgument_stmt(YangParser.Argument_stmtContext ctx); + + void enterLeafref_specification(YangParser.Leafref_specificationContext ctx); + + void exitLeafref_specification(YangParser.Leafref_specificationContext ctx); + + void enterError_app_tag_stmt(YangParser.Error_app_tag_stmtContext ctx); + + void exitError_app_tag_stmt(YangParser.Error_app_tag_stmtContext ctx); + + void enterData_def_stmt(YangParser.Data_def_stmtContext ctx); + + void exitData_def_stmt(YangParser.Data_def_stmtContext ctx); + + void enterIdentity_stmt(YangParser.Identity_stmtContext ctx); + + void exitIdentity_stmt(YangParser.Identity_stmtContext ctx); + + void enterDeviate_not_supported_stmt( + YangParser.Deviate_not_supported_stmtContext ctx); + + void exitDeviate_not_supported_stmt( + YangParser.Deviate_not_supported_stmtContext ctx); + + void enterPrefix_stmt(YangParser.Prefix_stmtContext ctx); + + void exitPrefix_stmt(YangParser.Prefix_stmtContext ctx); + + void enterMeta_stmts(YangParser.Meta_stmtsContext ctx); + + void exitMeta_stmts(YangParser.Meta_stmtsContext ctx); + + void enterLinkage_stmts(YangParser.Linkage_stmtsContext ctx); + + void exitLinkage_stmts(YangParser.Linkage_stmtsContext ctx); + + void enterGrouping_stmt(YangParser.Grouping_stmtContext ctx); + + void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx); + + void enterFeature_stmt(YangParser.Feature_stmtContext ctx); + + void exitFeature_stmt(YangParser.Feature_stmtContext ctx); + + void enterYang(YangParser.YangContext ctx); + + void exitYang(YangParser.YangContext ctx); + + void enterIdentityref_specification( + YangParser.Identityref_specificationContext ctx); + + void exitIdentityref_specification( + YangParser.Identityref_specificationContext ctx); + + void enterNumerical_restrictions( + YangParser.Numerical_restrictionsContext ctx); + + void exitNumerical_restrictions(YangParser.Numerical_restrictionsContext ctx); + + void enterModule_header_stmts(YangParser.Module_header_stmtsContext ctx); + + void exitModule_header_stmts(YangParser.Module_header_stmtsContext ctx); + + void enterRequire_instance_stmt(YangParser.Require_instance_stmtContext ctx); + + void exitRequire_instance_stmt(YangParser.Require_instance_stmtContext ctx); + + void enterBit_stmt(YangParser.Bit_stmtContext ctx); + + void exitBit_stmt(YangParser.Bit_stmtContext ctx); + + void enterType_stmt(YangParser.Type_stmtContext ctx); + + void exitType_stmt(YangParser.Type_stmtContext ctx); + + void enterPattern_stmt(YangParser.Pattern_stmtContext ctx); + + void exitPattern_stmt(YangParser.Pattern_stmtContext ctx); + + void enterDeviation_stmt(YangParser.Deviation_stmtContext ctx); + + void exitDeviation_stmt(YangParser.Deviation_stmtContext ctx); + + void enterDeviate_replace_stmt(YangParser.Deviate_replace_stmtContext ctx); + + void exitDeviate_replace_stmt(YangParser.Deviate_replace_stmtContext ctx); + + void enterKey_stmt(YangParser.Key_stmtContext ctx); + + void exitKey_stmt(YangParser.Key_stmtContext ctx); + + void enterRequire_instance_arg(YangParser.Require_instance_argContext ctx); + + void exitRequire_instance_arg(YangParser.Require_instance_argContext ctx); + + void enterLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx); + + void exitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx); + + void enterAugment_stmt(YangParser.Augment_stmtContext ctx); + + void exitAugment_stmt(YangParser.Augment_stmtContext ctx); + + void enterDeviate_delete_stmt(YangParser.Deviate_delete_stmtContext ctx); + + void exitDeviate_delete_stmt(YangParser.Deviate_delete_stmtContext ctx); + + void enterTypedef_stmt(YangParser.Typedef_stmtContext ctx); + + void exitTypedef_stmt(YangParser.Typedef_stmtContext ctx); + + void enterContainer_stmt(YangParser.Container_stmtContext ctx); + + void exitContainer_stmt(YangParser.Container_stmtContext ctx); + + void enterBelongs_to_stmt(YangParser.Belongs_to_stmtContext ctx); + + void exitBelongs_to_stmt(YangParser.Belongs_to_stmtContext ctx); + + void enterBase_stmt(YangParser.Base_stmtContext ctx); + + void exitBase_stmt(YangParser.Base_stmtContext ctx); + + void enterYang_version_stmt(YangParser.Yang_version_stmtContext ctx); + + void exitYang_version_stmt(YangParser.Yang_version_stmtContext ctx); + + void enterReference_stmt(YangParser.Reference_stmtContext ctx); + + void exitReference_stmt(YangParser.Reference_stmtContext ctx); + + void enterYin_element_stmt(YangParser.Yin_element_stmtContext ctx); + + void exitYin_element_stmt(YangParser.Yin_element_stmtContext ctx); + + void enterLeaf_stmt(YangParser.Leaf_stmtContext ctx); + + void exitLeaf_stmt(YangParser.Leaf_stmtContext ctx); + + void enterCase_stmt(YangParser.Case_stmtContext ctx); + + void exitCase_stmt(YangParser.Case_stmtContext ctx); + + void enterModule_stmt(YangParser.Module_stmtContext ctx); + + void exitModule_stmt(YangParser.Module_stmtContext ctx); + + void enterRpc_stmt(YangParser.Rpc_stmtContext ctx); + + void exitRpc_stmt(YangParser.Rpc_stmtContext ctx); + + void enterType_body_stmts(YangParser.Type_body_stmtsContext ctx); + + void exitType_body_stmts(YangParser.Type_body_stmtsContext ctx); + + void enterExtension_stmt(YangParser.Extension_stmtContext ctx); + + void exitExtension_stmt(YangParser.Extension_stmtContext ctx); + + void enterSubmodule_header_stmts( + YangParser.Submodule_header_stmtsContext ctx); + + void exitSubmodule_header_stmts(YangParser.Submodule_header_stmtsContext ctx); + + void enterRefine_container_stmts( + YangParser.Refine_container_stmtsContext ctx); + + void exitRefine_container_stmts(YangParser.Refine_container_stmtsContext ctx); + + void enterValue_stmt(YangParser.Value_stmtContext ctx); + + void exitValue_stmt(YangParser.Value_stmtContext ctx); + + void enterRefine_list_stmts(YangParser.Refine_list_stmtsContext ctx); + + void exitRefine_list_stmts(YangParser.Refine_list_stmtsContext ctx); + + void enterDefault_stmt(YangParser.Default_stmtContext ctx); + + void exitDefault_stmt(YangParser.Default_stmtContext ctx); + + void enterRevision_stmts(YangParser.Revision_stmtsContext ctx); + + void exitRevision_stmts(YangParser.Revision_stmtsContext ctx); + + void enterAnyxml_stmt(YangParser.Anyxml_stmtContext ctx); + + void exitAnyxml_stmt(YangParser.Anyxml_stmtContext ctx); + + void enterStatus_stmt(YangParser.Status_stmtContext ctx); + + void exitStatus_stmt(YangParser.Status_stmtContext ctx); + + void enterContact_stmt(YangParser.Contact_stmtContext ctx); + + void exitContact_stmt(YangParser.Contact_stmtContext ctx); + + void enterIdentifier_stmt(YangParser.Identifier_stmtContext ctx); + + void exitIdentifier_stmt(YangParser.Identifier_stmtContext ctx); + + void enterString(YangParser.StringContext ctx); + + void exitString(YangParser.StringContext ctx); + + void enterRefine_choice_stmts(YangParser.Refine_choice_stmtsContext ctx); + + void exitRefine_choice_stmts(YangParser.Refine_choice_stmtsContext ctx); + + void enterMandatory_arg(YangParser.Mandatory_argContext ctx); + + void exitMandatory_arg(YangParser.Mandatory_argContext ctx); + + void enterRefine_stmt(YangParser.Refine_stmtContext ctx); + + void exitRefine_stmt(YangParser.Refine_stmtContext ctx); + + void enterInstance_identifier_specification( + YangParser.Instance_identifier_specificationContext ctx); + + void exitInstance_identifier_specification( + YangParser.Instance_identifier_specificationContext ctx); + + void enterBits_specification(YangParser.Bits_specificationContext ctx); + + void exitBits_specification(YangParser.Bits_specificationContext ctx); + + void enterWhen_stmt(YangParser.When_stmtContext ctx); + + void exitWhen_stmt(YangParser.When_stmtContext ctx); + + void enterString_restrictions(YangParser.String_restrictionsContext ctx); + + void exitString_restrictions(YangParser.String_restrictionsContext ctx); + + void enterRefine_leaf_stmts(YangParser.Refine_leaf_stmtsContext ctx); + + void exitRefine_leaf_stmts(YangParser.Refine_leaf_stmtsContext ctx); + + void enterMandatory_stmt(YangParser.Mandatory_stmtContext ctx); + + void exitMandatory_stmt(YangParser.Mandatory_stmtContext ctx); + + void enterOrdered_by_arg(YangParser.Ordered_by_argContext ctx); + + void exitOrdered_by_arg(YangParser.Ordered_by_argContext ctx); + + void enterMin_elements_stmt(YangParser.Min_elements_stmtContext ctx); + + void exitMin_elements_stmt(YangParser.Min_elements_stmtContext ctx); + + void enterStmtend(YangParser.StmtendContext ctx); + + void exitStmtend(YangParser.StmtendContext ctx); + + void enterRefine_anyxml_stmts(YangParser.Refine_anyxml_stmtsContext ctx); + + void exitRefine_anyxml_stmts(YangParser.Refine_anyxml_stmtsContext ctx); + + void enterDescription_stmt(YangParser.Description_stmtContext ctx); + + void exitDescription_stmt(YangParser.Description_stmtContext ctx); + + void enterPath_stmt(YangParser.Path_stmtContext ctx); + + void exitPath_stmt(YangParser.Path_stmtContext ctx); + + void enterInclude_stmt(YangParser.Include_stmtContext ctx); + + void exitInclude_stmt(YangParser.Include_stmtContext ctx); + + void enterUnits_stmt(YangParser.Units_stmtContext ctx); + + void exitUnits_stmt(YangParser.Units_stmtContext ctx); + + void enterUses_stmt(YangParser.Uses_stmtContext ctx); + + void exitUses_stmt(YangParser.Uses_stmtContext ctx); + + void enterOrdered_by_stmt(YangParser.Ordered_by_stmtContext ctx); + + void exitOrdered_by_stmt(YangParser.Ordered_by_stmtContext ctx); + + void enterRange_stmt(YangParser.Range_stmtContext ctx); + + void exitRange_stmt(YangParser.Range_stmtContext ctx); + + void enterNamespace_stmt(YangParser.Namespace_stmtContext ctx); + + void exitNamespace_stmt(YangParser.Namespace_stmtContext ctx); + + void enterDeviate_add_stmt(YangParser.Deviate_add_stmtContext ctx); + + void exitDeviate_add_stmt(YangParser.Deviate_add_stmtContext ctx); + + void enterShort_case_stmt(YangParser.Short_case_stmtContext ctx); + + void exitShort_case_stmt(YangParser.Short_case_stmtContext ctx); + + void enterConfig_stmt(YangParser.Config_stmtContext ctx); + + void exitConfig_stmt(YangParser.Config_stmtContext ctx); + + void enterEnum_stmt(YangParser.Enum_stmtContext ctx); + + void exitEnum_stmt(YangParser.Enum_stmtContext ctx); + + void enterYin_element_arg(YangParser.Yin_element_argContext ctx); + + void exitYin_element_arg(YangParser.Yin_element_argContext ctx); + + void enterOrganization_stmt(YangParser.Organization_stmtContext ctx); + + void exitOrganization_stmt(YangParser.Organization_stmtContext ctx); + + void enterUnion_specification(YangParser.Union_specificationContext ctx); + + void exitUnion_specification(YangParser.Union_specificationContext ctx); + + void enterMax_value_arg(YangParser.Max_value_argContext ctx); + + void exitMax_value_arg(YangParser.Max_value_argContext ctx); + + void enterSubmodule_stmt(YangParser.Submodule_stmtContext ctx); + + void exitSubmodule_stmt(YangParser.Submodule_stmtContext ctx); + + void enterStatus_arg(YangParser.Status_argContext ctx); + + void exitStatus_arg(YangParser.Status_argContext ctx); + + void enterList_stmt(YangParser.List_stmtContext ctx); + + void exitList_stmt(YangParser.List_stmtContext ctx); + + void enterMax_elements_stmt(YangParser.Max_elements_stmtContext ctx); + + void exitMax_elements_stmt(YangParser.Max_elements_stmtContext ctx); + + void enterImport_stmt(YangParser.Import_stmtContext ctx); + + void exitImport_stmt(YangParser.Import_stmtContext ctx); + + void enterConfig_arg(YangParser.Config_argContext ctx); + + void exitConfig_arg(YangParser.Config_argContext ctx); + + void enterRevision_date_stmt(YangParser.Revision_date_stmtContext ctx); + + void exitRevision_date_stmt(YangParser.Revision_date_stmtContext ctx); + + void enterRefune_pom(YangParser.Refune_pomContext ctx); + + void exitRefune_pom(YangParser.Refune_pomContext ctx); + + void enterPresence_stmt(YangParser.Presence_stmtContext ctx); + + void exitPresence_stmt(YangParser.Presence_stmtContext ctx); + + void enterFraction_digits_stmt(YangParser.Fraction_digits_stmtContext ctx); + + void exitFraction_digits_stmt(YangParser.Fraction_digits_stmtContext ctx); + + void enterNotification_stmt(YangParser.Notification_stmtContext ctx); + + void exitNotification_stmt(YangParser.Notification_stmtContext ctx); + + void enterInput_stmt(YangParser.Input_stmtContext ctx); + + void exitInput_stmt(YangParser.Input_stmtContext ctx); + + void enterUses_augment_stmt(YangParser.Uses_augment_stmtContext ctx); + + void exitUses_augment_stmt(YangParser.Uses_augment_stmtContext ctx); + + void enterRefine_case_stmts(YangParser.Refine_case_stmtsContext ctx); + + void exitRefine_case_stmts(YangParser.Refine_case_stmtsContext ctx); + + void enterDecimal64_specification( + YangParser.Decimal64_specificationContext ctx); + + void exitDecimal64_specification( + YangParser.Decimal64_specificationContext ctx); + + void enterIf_feature_stmt(YangParser.If_feature_stmtContext ctx); + + void exitIf_feature_stmt(YangParser.If_feature_stmtContext ctx); + + void enterRevision_stmt(YangParser.Revision_stmtContext ctx); + + void exitRevision_stmt(YangParser.Revision_stmtContext ctx); + + void enterLength_stmt(YangParser.Length_stmtContext ctx); + + void exitLength_stmt(YangParser.Length_stmtContext ctx); + + void enterMust_stmt(YangParser.Must_stmtContext ctx); + + void exitMust_stmt(YangParser.Must_stmtContext ctx); + + void enterBody_stmts(YangParser.Body_stmtsContext ctx); + + void exitBody_stmts(YangParser.Body_stmtsContext ctx); + + void enterError_message_stmt(YangParser.Error_message_stmtContext ctx); + + void exitError_message_stmt(YangParser.Error_message_stmtContext ctx); + + void enterUnique_stmt(YangParser.Unique_stmtContext ctx); + + void exitUnique_stmt(YangParser.Unique_stmtContext ctx); + + void enterChoice_stmt(YangParser.Choice_stmtContext ctx); + + void exitChoice_stmt(YangParser.Choice_stmtContext ctx); + + void enterOutput_stmt(YangParser.Output_stmtContext ctx); + + void exitOutput_stmt(YangParser.Output_stmtContext ctx); +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserVisitor.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserVisitor.java new file mode 100644 index 0000000000..38d6dfb238 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/antlrv4/code/gen/YangParserVisitor.java @@ -0,0 +1,227 @@ +/* + * 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.controller.antlrv4.code.gen; + +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +public interface YangParserVisitor extends ParseTreeVisitor { + T visitEnum_specification(YangParser.Enum_specificationContext ctx); + + T visitRefine_leaf_list_stmts(YangParser.Refine_leaf_list_stmtsContext ctx); + + T visitPosition_stmt(YangParser.Position_stmtContext ctx); + + T visitArgument_stmt(YangParser.Argument_stmtContext ctx); + + T visitLeafref_specification(YangParser.Leafref_specificationContext ctx); + + T visitError_app_tag_stmt(YangParser.Error_app_tag_stmtContext ctx); + + T visitData_def_stmt(YangParser.Data_def_stmtContext ctx); + + T visitIdentity_stmt(YangParser.Identity_stmtContext ctx); + + T visitDeviate_not_supported_stmt( + YangParser.Deviate_not_supported_stmtContext ctx); + + T visitPrefix_stmt(YangParser.Prefix_stmtContext ctx); + + T visitMeta_stmts(YangParser.Meta_stmtsContext ctx); + + T visitLinkage_stmts(YangParser.Linkage_stmtsContext ctx); + + T visitGrouping_stmt(YangParser.Grouping_stmtContext ctx); + + T visitFeature_stmt(YangParser.Feature_stmtContext ctx); + + T visitYang(YangParser.YangContext ctx); + + T visitIdentityref_specification( + YangParser.Identityref_specificationContext ctx); + + T visitNumerical_restrictions(YangParser.Numerical_restrictionsContext ctx); + + T visitModule_header_stmts(YangParser.Module_header_stmtsContext ctx); + + T visitRequire_instance_stmt(YangParser.Require_instance_stmtContext ctx); + + T visitBit_stmt(YangParser.Bit_stmtContext ctx); + + T visitType_stmt(YangParser.Type_stmtContext ctx); + + T visitPattern_stmt(YangParser.Pattern_stmtContext ctx); + + T visitDeviation_stmt(YangParser.Deviation_stmtContext ctx); + + T visitDeviate_replace_stmt(YangParser.Deviate_replace_stmtContext ctx); + + T visitKey_stmt(YangParser.Key_stmtContext ctx); + + T visitRequire_instance_arg(YangParser.Require_instance_argContext ctx); + + T visitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx); + + T visitAugment_stmt(YangParser.Augment_stmtContext ctx); + + T visitDeviate_delete_stmt(YangParser.Deviate_delete_stmtContext ctx); + + T visitTypedef_stmt(YangParser.Typedef_stmtContext ctx); + + T visitContainer_stmt(YangParser.Container_stmtContext ctx); + + T visitBelongs_to_stmt(YangParser.Belongs_to_stmtContext ctx); + + T visitBase_stmt(YangParser.Base_stmtContext ctx); + + T visitYang_version_stmt(YangParser.Yang_version_stmtContext ctx); + + T visitReference_stmt(YangParser.Reference_stmtContext ctx); + + T visitYin_element_stmt(YangParser.Yin_element_stmtContext ctx); + + T visitLeaf_stmt(YangParser.Leaf_stmtContext ctx); + + T visitCase_stmt(YangParser.Case_stmtContext ctx); + + T visitModule_stmt(YangParser.Module_stmtContext ctx); + + T visitRpc_stmt(YangParser.Rpc_stmtContext ctx); + + T visitType_body_stmts(YangParser.Type_body_stmtsContext ctx); + + T visitExtension_stmt(YangParser.Extension_stmtContext ctx); + + T visitSubmodule_header_stmts(YangParser.Submodule_header_stmtsContext ctx); + + T visitRefine_container_stmts(YangParser.Refine_container_stmtsContext ctx); + + T visitValue_stmt(YangParser.Value_stmtContext ctx); + + T visitRefine_list_stmts(YangParser.Refine_list_stmtsContext ctx); + + T visitDefault_stmt(YangParser.Default_stmtContext ctx); + + T visitRevision_stmts(YangParser.Revision_stmtsContext ctx); + + T visitAnyxml_stmt(YangParser.Anyxml_stmtContext ctx); + + T visitStatus_stmt(YangParser.Status_stmtContext ctx); + + T visitContact_stmt(YangParser.Contact_stmtContext ctx); + + T visitIdentifier_stmt(YangParser.Identifier_stmtContext ctx); + + T visitString(YangParser.StringContext ctx); + + T visitRefine_choice_stmts(YangParser.Refine_choice_stmtsContext ctx); + + T visitMandatory_arg(YangParser.Mandatory_argContext ctx); + + T visitRefine_stmt(YangParser.Refine_stmtContext ctx); + + T visitInstance_identifier_specification( + YangParser.Instance_identifier_specificationContext ctx); + + T visitBits_specification(YangParser.Bits_specificationContext ctx); + + T visitWhen_stmt(YangParser.When_stmtContext ctx); + + T visitString_restrictions(YangParser.String_restrictionsContext ctx); + + T visitRefine_leaf_stmts(YangParser.Refine_leaf_stmtsContext ctx); + + T visitMandatory_stmt(YangParser.Mandatory_stmtContext ctx); + + T visitOrdered_by_arg(YangParser.Ordered_by_argContext ctx); + + T visitMin_elements_stmt(YangParser.Min_elements_stmtContext ctx); + + T visitStmtend(YangParser.StmtendContext ctx); + + T visitRefine_anyxml_stmts(YangParser.Refine_anyxml_stmtsContext ctx); + + T visitDescription_stmt(YangParser.Description_stmtContext ctx); + + T visitPath_stmt(YangParser.Path_stmtContext ctx); + + T visitInclude_stmt(YangParser.Include_stmtContext ctx); + + T visitUnits_stmt(YangParser.Units_stmtContext ctx); + + T visitUses_stmt(YangParser.Uses_stmtContext ctx); + + T visitOrdered_by_stmt(YangParser.Ordered_by_stmtContext ctx); + + T visitRange_stmt(YangParser.Range_stmtContext ctx); + + T visitNamespace_stmt(YangParser.Namespace_stmtContext ctx); + + T visitDeviate_add_stmt(YangParser.Deviate_add_stmtContext ctx); + + T visitShort_case_stmt(YangParser.Short_case_stmtContext ctx); + + T visitConfig_stmt(YangParser.Config_stmtContext ctx); + + T visitEnum_stmt(YangParser.Enum_stmtContext ctx); + + T visitYin_element_arg(YangParser.Yin_element_argContext ctx); + + T visitOrganization_stmt(YangParser.Organization_stmtContext ctx); + + T visitUnion_specification(YangParser.Union_specificationContext ctx); + + T visitMax_value_arg(YangParser.Max_value_argContext ctx); + + T visitSubmodule_stmt(YangParser.Submodule_stmtContext ctx); + + T visitStatus_arg(YangParser.Status_argContext ctx); + + T visitList_stmt(YangParser.List_stmtContext ctx); + + T visitMax_elements_stmt(YangParser.Max_elements_stmtContext ctx); + + T visitImport_stmt(YangParser.Import_stmtContext ctx); + + T visitConfig_arg(YangParser.Config_argContext ctx); + + T visitRevision_date_stmt(YangParser.Revision_date_stmtContext ctx); + + T visitRefune_pom(YangParser.Refune_pomContext ctx); + + T visitPresence_stmt(YangParser.Presence_stmtContext ctx); + + T visitFraction_digits_stmt(YangParser.Fraction_digits_stmtContext ctx); + + T visitNotification_stmt(YangParser.Notification_stmtContext ctx); + + T visitInput_stmt(YangParser.Input_stmtContext ctx); + + T visitUses_augment_stmt(YangParser.Uses_augment_stmtContext ctx); + + T visitRefine_case_stmts(YangParser.Refine_case_stmtsContext ctx); + + T visitDecimal64_specification(YangParser.Decimal64_specificationContext ctx); + + T visitIf_feature_stmt(YangParser.If_feature_stmtContext ctx); + + T visitRevision_stmt(YangParser.Revision_stmtContext ctx); + + T visitLength_stmt(YangParser.Length_stmtContext ctx); + + T visitMust_stmt(YangParser.Must_stmtContext ctx); + + T visitBody_stmts(YangParser.Body_stmtsContext ctx); + + T visitError_message_stmt(YangParser.Error_message_stmtContext ctx); + + T visitUnique_stmt(YangParser.Unique_stmtContext ctx); + + T visitChoice_stmt(YangParser.Choice_stmtContext ctx); + + T visitOutput_stmt(YangParser.Output_stmtContext ctx); +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AbstractChildNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AbstractChildNodeBuilder.java new file mode 100644 index 0000000000..cc950eccef --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AbstractChildNodeBuilder.java @@ -0,0 +1,40 @@ +/* + * 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.controller.model.parser.api; + +import java.util.HashSet; +import java.util.Set; + +import org.opendaylight.controller.yang.common.QName; + +public abstract class AbstractChildNodeBuilder implements ChildNodeBuilder { + + private final QName qname; + protected final Set childNodes = new HashSet(); + protected final Set groupings = new HashSet(); + + protected AbstractChildNodeBuilder(QName qname) { + this.qname = qname; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public void addChildNode(DataSchemaNodeBuilder childNode) { + childNodes.add(childNode); + } + + @Override + public void addGrouping(GroupingBuilder grouping) { + groupings.add(grouping); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AugmentationSchemaBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AugmentationSchemaBuilder.java new file mode 100644 index 0000000000..fe2fc0e677 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AugmentationSchemaBuilder.java @@ -0,0 +1,26 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +/** + * Interface for builders of 'augment' statement. + */ +public interface AugmentationSchemaBuilder extends ChildNodeBuilder, TypeDefinitionAwareBuilder { + + void setDescription(String description); + void setReference(String reference); + void setStatus(Status status); + + AugmentationSchema build(); + SchemaPath getTargetPath(); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AugmentationTargetBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AugmentationTargetBuilder.java new file mode 100644 index 0000000000..bd71a8aef8 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/AugmentationTargetBuilder.java @@ -0,0 +1,23 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.model.api.AugmentationSchema; + +/** + * Interface for builders of those nodes, which can be augmentation targets. + */ +public interface AugmentationTargetBuilder { + + /** + * Add augment, which points to this node. + * @param augment augment which points to this node + */ + void addAugmentation(AugmentationSchema augment); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/Builder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/Builder.java new file mode 100644 index 0000000000..fede31fefc --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/Builder.java @@ -0,0 +1,17 @@ +/* + * 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.controller.model.parser.api; + +/** + * Parent interface for all builder interfaces. + */ +public interface Builder { + + Object build(); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/ChildNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/ChildNodeBuilder.java new file mode 100644 index 0000000000..0f60154714 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/ChildNodeBuilder.java @@ -0,0 +1,22 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.common.QName; + +/** + * Interface for all yang data-node containers [augment, case, container, grouping, list, module, notification]. + */ +public interface ChildNodeBuilder extends Builder { + + QName getQName(); + void addChildNode(DataSchemaNodeBuilder childNode); + void addGrouping(GroupingBuilder groupingBuilder); + void addUsesNode(UsesNodeBuilder usesBuilder); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/DataSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/DataSchemaNodeBuilder.java new file mode 100644 index 0000000000..1eaf1af7c2 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/DataSchemaNodeBuilder.java @@ -0,0 +1,21 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.model.api.DataSchemaNode; + +/** + * Interface for all yang data-schema nodes [anyxml, case, container, grouping, list, module, notification]. + */ +public interface DataSchemaNodeBuilder extends SchemaNodeBuilder { + + DataSchemaNode build(); + void setAugmenting(boolean augmenting); + void setConfiguration(boolean configuration); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/GroupingBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/GroupingBuilder.java new file mode 100644 index 0000000000..22632ab223 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/GroupingBuilder.java @@ -0,0 +1,19 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.model.api.GroupingDefinition; + +/** + * Interface for builders of 'grouping' statement. + */ +public interface GroupingBuilder extends ChildNodeBuilder, SchemaNodeBuilder, TypeDefinitionAwareBuilder { + + GroupingDefinition build(); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/SchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/SchemaNodeBuilder.java new file mode 100644 index 0000000000..c63104ebc4 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/SchemaNodeBuilder.java @@ -0,0 +1,26 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + + +/** + * Interface for all builders of SchemaNode nodes. + */ +public interface SchemaNodeBuilder extends Builder { + + QName getQName(); + void setPath(SchemaPath schemaPath); + void setDescription(String description); + void setReference(String reference); + void setStatus(Status status); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeAwareBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeAwareBuilder.java new file mode 100644 index 0000000000..64ccb119cb --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeAwareBuilder.java @@ -0,0 +1,21 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +/** + * Builders of all nodes, which can have 'type' statement must implement this interface. + * [typedef, type, leaf, leaf-list, deviate] + */ +public interface TypeAwareBuilder { + + TypeDefinition getType(); + void setType(TypeDefinition type); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeDefinitionAwareBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeDefinitionAwareBuilder.java new file mode 100644 index 0000000000..bfa9a10b1c --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeDefinitionAwareBuilder.java @@ -0,0 +1,18 @@ +/* + * 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.controller.model.parser.api; + +/** + * Builders of all nodes, which can have 'typedef' statement must implement this interface. + * [module, submodule, container, list, grouping, rpc, input, output, notification] + */ +public interface TypeDefinitionAwareBuilder { + + void addTypedef(TypeDefinitionBuilder typedefBuilder); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeDefinitionBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeDefinitionBuilder.java new file mode 100644 index 0000000000..9a7b97e5c0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/TypeDefinitionBuilder.java @@ -0,0 +1,23 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + + +/** + * Interface for builders of 'typedef' statement. + */ +public interface TypeDefinitionBuilder { + + QName getQName(); + TypeDefinition getBaseType(); + TypeDefinition build(); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/UsesNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/UsesNodeBuilder.java new file mode 100644 index 0000000000..13ecd15001 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/api/UsesNodeBuilder.java @@ -0,0 +1,21 @@ +/* + * 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.controller.model.parser.api; + +import org.opendaylight.controller.yang.model.api.UsesNode; + +/** + * Interface for builders of 'uses' statement. + */ +public interface UsesNodeBuilder { + + void addAugment(AugmentationSchemaBuilder builder); + + UsesNode build(); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/AugmentationSchemaBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/AugmentationSchemaBuilderImpl.java new file mode 100644 index 0000000000..2ece5a0715 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/AugmentationSchemaBuilderImpl.java @@ -0,0 +1,306 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.model.parser.api.AugmentationSchemaBuilder; +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.model.parser.util.YangModelBuilderHelper; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +public class AugmentationSchemaBuilderImpl implements AugmentationSchemaBuilder { + + private final AugmentationSchemaImpl instance; + private final SchemaPath augmentTarget; + final Set childNodes = new HashSet(); + final Set groupings = new HashSet(); + private final Set usesNodes = new HashSet(); + + AugmentationSchemaBuilderImpl(String augmentPath) { + SchemaPath targetPath = YangModelBuilderHelper.parsePath(augmentPath); + augmentTarget = targetPath; + instance = new AugmentationSchemaImpl(targetPath); + } + + @Override + public void addChildNode(DataSchemaNodeBuilder childNode) { + childNodes.add(childNode); + } + + @Override + public void addGrouping(GroupingBuilder grouping) { + groupings.add(grouping); + } + + /** + * Always returns null. + */ + @Override + public QName getQName() { + return null; + } + + @Override + public AugmentationSchema build() { + + // CHILD NODES + Map childs = new HashMap(); + for(DataSchemaNodeBuilder node : childNodes) { + childs.put(node.getQName(), node.build()); + } + instance.setChildNodes(childs); + + // GROUPINGS + Set groupingDefinitions = new HashSet(); + for(GroupingBuilder builder : groupings) { + groupingDefinitions.add(builder.build()); + } + instance.setGroupings(groupingDefinitions); + + // USES + Set usesNodeDefinitions = new HashSet(); + for(UsesNodeBuilder builder : usesNodes) { + usesNodeDefinitions.add(builder.build()); + } + instance.setUses(usesNodeDefinitions); + + return instance; + } + + @Override + public void addUsesNode(UsesNodeBuilder usesBuilder) { + usesNodes.add(usesBuilder); + } + + @Override + public void addTypedef(TypeDefinitionBuilder type) { + throw new UnsupportedOperationException("Augmentation can not contains type definitions"); + } + + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + @Override + public SchemaPath getTargetPath() { + return augmentTarget; + } + + + private static class AugmentationSchemaImpl implements AugmentationSchema { + + private final SchemaPath targetPath; + private Map childNodes; + private Set groupings; + private Set uses; + + private String description; + private String reference; + private Status status; + + private AugmentationSchemaImpl(SchemaPath targetPath) { + this.targetPath = targetPath; + } + + + @Override + public SchemaPath getTargetPath() { + return targetPath; + } + + @Override + public Set getChildNodes() { + return new HashSet(childNodes.values()); + } + private void setChildNodes(Map childNodes) { + this.childNodes = childNodes; + } + + @Override + public Set getGroupings() { + return groupings; + } + private void setGroupings(Set groupings) { + this.groupings = groupings; + } + + @Override + public Set getUses() { + return uses; + } + private void setUses(Set uses) { + this.uses = uses; + } + + /** + * This method always returns null, because augmentation can not contains type definitions. + */ + @Override + public Set> getTypeDefinitions() { + return null; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + private void setStatus(Status status) { + this.status = status; + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + return childNodes.get(name); + } + + @Override + public DataSchemaNode getDataChildByName(String name) { + DataSchemaNode result = null; + for(Map.Entry entry : childNodes.entrySet()) { + if(entry.getKey().getLocalName().equals(name)) { + result = entry.getValue(); + break; + } + } + return result; + } + + @Override + public int hashCode() { + final int prime = 17; + int result = 1; + result = prime * result + ((targetPath == null) ? 0 : targetPath.hashCode()); + result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode()); + result = prime * result + ((groupings == null) ? 0 : groupings.hashCode()); + result = prime * result + ((uses == null) ? 0 : uses.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + AugmentationSchemaImpl other = (AugmentationSchemaImpl) obj; + if (targetPath == null) { + if (other.targetPath != null) { + return false; + } + } else if (!targetPath.equals(other.targetPath)) { + return false; + } + if (childNodes == null) { + if (other.childNodes != null) { + return false; + } + } else if (!childNodes.equals(other.childNodes)) { + return false; + } + if (groupings == null) { + if (other.groupings != null) { + return false; + } + } else if (!groupings.equals(other.groupings)) { + return false; + } + if (uses == null) { + if (other.uses != null) { + return false; + } + } else if (!uses.equals(other.uses)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (status == null) { + if (other.status != null) { + return false; + } + } else if (!status.equals(other.status)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(AugmentationSchemaImpl.class.getSimpleName()); + sb.append("["); + sb.append("targetPath="+ targetPath); + sb.append(", childNodes="+ childNodes.values()); + sb.append(", groupings="+ groupings); + sb.append(", uses="+ uses); + sb.append("]"); + return sb.toString(); + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ContainerSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ContainerSchemaNodeBuilder.java new file mode 100644 index 0000000000..1651bfcb54 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ContainerSchemaNodeBuilder.java @@ -0,0 +1,468 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.model.parser.api.AbstractChildNodeBuilder; +import org.opendaylight.controller.model.parser.api.AugmentationTargetBuilder; +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionAwareBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.ConstraintDefinition; +import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.MustDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +public class ContainerSchemaNodeBuilder extends AbstractChildNodeBuilder implements TypeDefinitionAwareBuilder, MustAwareBuilder, AugmentationTargetBuilder, DataSchemaNodeBuilder { + + private final ContainerSchemaNodeImpl instance; + + private final Set addedTypedefs = new HashSet(); + private final Set augmentations = new HashSet(); + private final Set addedUsesNodes = new HashSet(); + private MustDefinitionBuilder mustDefinitionBuilder; + + ContainerSchemaNodeBuilder(QName qname) { + super(qname); + instance = new ContainerSchemaNodeImpl(qname); + } + + @Override + public ContainerSchemaNode build() { + // CHILD NODES + Map childs = new HashMap(); + for (DataSchemaNodeBuilder node : childNodes) { + childs.put(node.getQName(), node.build()); + } + instance.setChildNodes(childs); + + // GROUPINGS + Set groupingDefinitions = new HashSet(); + for (GroupingBuilder builder : groupings) { + groupingDefinitions.add(builder.build()); + } + instance.setGroupings(groupingDefinitions); + + // TYPEDEFS + Set> typedefs = new HashSet>(); + for(TypeDefinitionBuilder entry : addedTypedefs) { + typedefs.add(entry.build()); + } + instance.setTypeDefinitions(typedefs); + + // USES + Set uses = new HashSet(); + for (UsesNodeBuilder builder : addedUsesNodes) { + uses.add(builder.build()); + } + instance.setUses(uses); + + // MUST definition + if(mustDefinitionBuilder != null) { + MustDefinition md = mustDefinitionBuilder.build(); + instance.setMustStatement(md); + } + + instance.setAvailableAugmentations(augmentations); + + return instance; + } + + + @Override + public void addTypedef(TypeDefinitionBuilder type) { + addedTypedefs.add(type); + } + + @Override + public void addAugmentation(AugmentationSchema augment) { + augmentations.add(augment); + } + + @Override + public void setPath(SchemaPath schemaPath) { + instance.setPath(schemaPath); + } + + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + @Override + public void setAugmenting(boolean augmenting) { + instance.setAugmenting(augmenting); + } + + @Override + public void setConfiguration(boolean configuration) { + instance.setConfiguration(configuration); + } + + public void setConstraints(ConstraintDefinition constraints) { + instance.setConstraints(constraints); + } + + @Override + public void addUsesNode(UsesNodeBuilder usesNodeBuilder) { + addedUsesNodes.add(usesNodeBuilder); + } + + public void setPresenceContainer(boolean presence) { + instance.setPresenceContainer(presence); + } + + @Override + public void setMustDefinitionBuilder(MustDefinitionBuilder mustDefinitionBuilder) { + this.mustDefinitionBuilder = mustDefinitionBuilder; + } + + + private class ContainerSchemaNodeImpl implements ContainerSchemaNode { + + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status = Status.CURRENT; + + private boolean augmenting; + private boolean configuration; + private ConstraintDefinition constraints; + + private Set augmentations; + + private Map childNodes; + private Set groupings; + private Set> typeDefinitions; + + private Set uses; + private boolean presence; + + private MustDefinition mustDefinition; + + private ContainerSchemaNodeImpl(QName qname) { + this.qname = qname; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + private void setPath(SchemaPath path) { + this.path = path; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + private void setStatus(Status status) { + this.status = status; + } + + @Override + public boolean isAugmenting() { + return augmenting; + } + private void setAugmenting(boolean augmenting) { + this.augmenting = augmenting; + } + + @Override + public boolean isConfiguration() { + return configuration; + } + private void setConfiguration(boolean configuration) { + this.configuration = configuration; + } + + @Override + public ConstraintDefinition getConstraints() { + return constraints; + } + private void setConstraints(ConstraintDefinition constraints) { + this.constraints = constraints; + } + + @Override + public Set getAvailableAugmentations() { + return augmentations; + } + private void setAvailableAugmentations( + Set augmentations) { + this.augmentations = augmentations; + } + + @Override + public Set getChildNodes() { + return new HashSet(childNodes.values()); + } + private void setChildNodes(Map childNodes) { + this.childNodes = childNodes; + } + + @Override + public Set getGroupings() { + return groupings; + } + private void setGroupings(Set groupings) { + this.groupings = groupings; + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + return childNodes.get(name); + } + + @Override + public DataSchemaNode getDataChildByName(String name) { + DataSchemaNode result = null; + for (Map.Entry entry : childNodes.entrySet()) { + if (entry.getKey().getLocalName().equals(name)) { + result = entry.getValue(); + break; + } + } + return result; + } + + @Override + public Set getUses() { + return uses; + } + + private void setUses(Set uses) { + this.uses = uses; + } + + @Override + public boolean isPresenceContainer() { + return presence; + } + + private void setPresenceContainer(boolean presence) { + this.presence = presence; + } + + @Override + public MustDefinition getMustDefinition() { + return mustDefinition; + } + private void setMustStatement(MustDefinition mustDefinition) { + this.mustDefinition = mustDefinition; + } + + @Override + public Set> getTypeDefinitions() { + return typeDefinitions; + } + private void setTypeDefinitions(Set> typeDefinitions) { + this.typeDefinitions = typeDefinitions; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((qname == null) ? 0 : qname.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + (augmenting ? 1231 : 1237); + result = prime * result + (configuration ? 1231 : 1237); + result = prime * result + ((constraints == null) ? 0 : constraints.hashCode()); + result = prime * result + ((augmentations == null) ? 0 : augmentations.hashCode()); + result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode()); + result = prime * result + ((groupings == null) ? 0 : groupings.hashCode()); + result = prime * result + ((uses == null) ? 0 : uses.hashCode()); + result = prime * result + (presence ? 1231 : 1237); + result = prime * result + ((mustDefinition == null) ? 0 : mustDefinition.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ContainerSchemaNodeImpl other = (ContainerSchemaNodeImpl) obj; + if (qname == null) { + if (other.qname != null) { + return false; + } + } else if (!qname.equals(other.qname)) { + return false; + } + if (path == null) { + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (status == null) { + if (other.status != null) { + return false; + } + } else if (!status.equals(other.status)) { + return false; + } + if(augmenting != other.augmenting) { + return false; + } + if(configuration != other.configuration) { + return false; + } + if (constraints == null) { + if (other.constraints != null) { + return false; + } + } else if (!constraints.equals(other.constraints)) { + return false; + } + if (augmentations == null) { + if (other.augmentations != null) { + return false; + } + } else if (!augmentations.equals(other.augmentations)) { + return false; + } + if (childNodes == null) { + if (other.childNodes != null) { + return false; + } + } else if (!childNodes.equals(other.childNodes)) { + return false; + } + if (groupings == null) { + if (other.groupings != null) { + return false; + } + } else if (!groupings.equals(other.groupings)) { + return false; + } + if (uses == null) { + if (other.uses != null) { + return false; + } + } else if (!uses.equals(other.uses)) { + return false; + } + if(presence != other.presence) { + return false; + } + if (mustDefinition == null) { + if (other.mustDefinition != null) { + return false; + } + } else if (!mustDefinition.equals(other.mustDefinition)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( + ContainerSchemaNodeImpl.class.getSimpleName()); + sb.append("["); + sb.append("qname=" + qname); + sb.append(", path=" + path); + sb.append(", description=" + description); + sb.append(", reference=" + reference); + sb.append(", status=" + status); + sb.append(", augmenting=" + augmenting); + sb.append(", constraints=" + constraints); + sb.append(", augmentations=" + augmentations); + sb.append(", childNodes=" + childNodes.values()); + sb.append(", groupings=" + groupings); + sb.append(", uses=" + uses); + sb.append(", presence=" + presence); + sb.append(", mustDefinition="+ mustDefinition); + sb.append("]"); + return sb.toString(); + } + } + +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/DeviationBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/DeviationBuilder.java new file mode 100644 index 0000000000..abc6198811 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/DeviationBuilder.java @@ -0,0 +1,108 @@ +/* + * 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.controller.model.parser.builder; + +import org.opendaylight.controller.model.parser.api.Builder; +import org.opendaylight.controller.model.parser.util.YangModelBuilderHelper; +import org.opendaylight.controller.yang.model.api.Deviation; +import org.opendaylight.controller.yang.model.api.MustDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Deviation.Deviate; + + +public class DeviationBuilder implements MustAwareBuilder, Builder { + + private final DeviationImpl instance; + private MustDefinitionBuilder mustDefinitionBuilder; + + DeviationBuilder(String targetPathStr) { + SchemaPath targetPath = YangModelBuilderHelper.parsePath(targetPathStr); + instance = new DeviationImpl(targetPath); + } + + @Override + public Deviation build() { + // MUST definition + if(mustDefinitionBuilder != null) { + MustDefinition md = mustDefinitionBuilder.build(); + instance.setMustDefinition(md); + } + return instance; + } + + public void setDeviate(String deviate) { + if(deviate.equals("not-supported")) { + instance.setDeviate(Deviate.NOT_SUPPORTED); + } else if(deviate.equals("add")) { + instance.setDeviate(Deviate.ADD); + } else if(deviate.equals("replace")) { + instance.setDeviate(Deviate.REPLACE); + } else if(deviate.equals("delete")) { + instance.setDeviate(Deviate.DELETE); + } else { + throw new IllegalArgumentException("Unsupported type of 'deviate' statement: "+ deviate); + } + } + + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setMustDefinitionBuilder(MustDefinitionBuilder mustDefinitionBuilder) { + this.mustDefinitionBuilder = mustDefinitionBuilder; + } + + private static class DeviationImpl implements Deviation { + + private SchemaPath targetPath; + private Deviate deviate; + private String reference; + private MustDefinition mustDefinition; + + private DeviationImpl(SchemaPath targetPath) { + this.targetPath = targetPath; + } + + @Override + public SchemaPath getTargetPath() { + return targetPath; + } + + @Override + public Deviate getDeviate() { + return deviate; + } + private void setDeviate(Deviate deviate) { + this.deviate = deviate; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public String toString() { + return DeviationImpl.class.getSimpleName() +"[targetPath="+ targetPath +", deviate="+ deviate +", reference="+ reference +", mustDefinition="+ mustDefinition +"]"; + } + + @Override + public MustDefinition getMustDefinition() { + return mustDefinition; + } + private void setMustDefinition(MustDefinition mustDefinition) { + this.mustDefinition = mustDefinition; + } + + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/FeatureBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/FeatureBuilder.java new file mode 100644 index 0000000000..e91d2fb687 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/FeatureBuilder.java @@ -0,0 +1,190 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.List; + +import org.opendaylight.controller.model.parser.api.SchemaNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.FeatureDefinition; +import org.opendaylight.controller.yang.model.api.SchemaNode; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + + +public class FeatureBuilder implements SchemaNodeBuilder { + + private final FeatureDefinitionImpl instance; + private final QName qname; + + FeatureBuilder(QName qname) { + this.qname = qname; + instance = new FeatureDefinitionImpl(qname); + } + + @Override + public SchemaNode build() { + return instance; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public void setPath(SchemaPath path) { + instance.setPath(path); + } + + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + private static class FeatureDefinitionImpl implements FeatureDefinition { + + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status; + + private FeatureDefinitionImpl(QName qname) { + this.qname = qname; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + private void setPath(SchemaPath path) { + this.path = path;; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + private void setStatus(Status status) { + this.status = status; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((qname == null) ? 0 : qname.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + FeatureDefinitionImpl other = (FeatureDefinitionImpl) obj; + if (qname == null) { + if (other.qname != null) { + return false; + } + } else if (!qname.equals(other.qname)) { + return false; + } + if (path == null) { + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (status == null) { + if (other.status != null) { + return false; + } + } else if (!status.equals(other.status)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(FeatureDefinitionImpl.class.getSimpleName()); + sb.append("[name="+ qname); + sb.append(", path="+ path); + sb.append(", description="+ description); + sb.append(", reference="+ reference); + sb.append(", status="+ status +"]"); + return sb.toString(); + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/GroupingBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/GroupingBuilderImpl.java new file mode 100644 index 0000000000..5ffe307344 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/GroupingBuilderImpl.java @@ -0,0 +1,245 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +public class GroupingBuilderImpl implements GroupingBuilder { + + private final GroupingDefinitionImpl instance; + private final Set childNodes = new HashSet(); + private final Set groupings = new HashSet(); + private final Set addedTypedefs = new HashSet(); + private final Set usesNodes = new HashSet(); + + GroupingBuilderImpl(QName qname) { + this.instance = new GroupingDefinitionImpl(qname); + } + + @Override + public GroupingDefinition build() { + // CHILD NODES + Map childs = new HashMap(); + for(DataSchemaNodeBuilder node : childNodes) { + childs.put(node.getQName(), node.build()); + } + instance.setChildNodes(childs); + + // GROUPINGS + Set groupingDefinitions = new HashSet(); + for(GroupingBuilder builder : groupings) { + groupingDefinitions.add(builder.build()); + } + instance.setGroupings(groupingDefinitions); + + // TYPEDEFS + Set> typedefs = new HashSet>(); + for (TypeDefinitionBuilder entry : addedTypedefs) { + typedefs.add(entry.build()); + } + instance.setTypeDefinitions(typedefs); + + // USES + Set usesNodeDefinitions = new HashSet(); + for(UsesNodeBuilder builder : usesNodes) { + usesNodeDefinitions.add(builder.build()); + } + instance.setUses(usesNodeDefinitions); + + return instance; + } + + @Override + public void addTypedef(TypeDefinitionBuilder type) { + addedTypedefs.add(type); + } + @Override + public void setPath(SchemaPath schemaPath) { + instance.setPath(schemaPath); + } + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + @Override + public void addChildNode(DataSchemaNodeBuilder childNode) { + childNodes.add(childNode); + } + + @Override + public void addGrouping(GroupingBuilder grouping) { + groupings.add(grouping); + } + + @Override + public void addUsesNode(UsesNodeBuilder usesBuilder) { + usesNodes.add(usesBuilder); + } + + + + private static class GroupingDefinitionImpl implements GroupingDefinition { + + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status; + + private Map childNodes; + private Set groupings; + private Set> typeDefinitions; + private Set uses; + + private GroupingDefinitionImpl(QName qname) { + this.qname = qname; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + private void setPath(SchemaPath path) { + this.path = path; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + private void setStatus(Status status) { + this.status = status; + } + + @Override + public Set getChildNodes() { + return new HashSet(childNodes.values()); + } + private void setChildNodes(Map childNodes) { + this.childNodes = childNodes; + } + + @Override + public Set getGroupings() { + return groupings; + } + private void setGroupings(Set groupings) { + this.groupings = groupings; + } + + @Override + public Set getUses() { + return uses; + } + private void setUses(Set uses) { + this.uses = uses; + } + + @Override + public Set> getTypeDefinitions() { + return typeDefinitions; + } + private void setTypeDefinitions(Set> typeDefinitions) { + this.typeDefinitions = typeDefinitions; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + return childNodes.get(name); + } + + @Override + public DataSchemaNode getDataChildByName(String name) { + DataSchemaNode result = null; + for(Map.Entry entry : childNodes.entrySet()) { + if(entry.getKey().getLocalName().equals(name)) { + result = entry.getValue(); + break; + } + } + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(GroupingDefinitionImpl.class.getSimpleName() +"[\n"); + sb.append("qname="+ qname +", \n"); + sb.append("path="+ path +", \n"); + sb.append("description="+ description +", \n"); + sb.append("reference="+ reference +", \n"); + sb.append("status="+ status +", \n"); + sb.append("childNodes="+ childNodes.values() +", \n"); + sb.append("groupings="+ groupings +"]"); + return sb.toString(); + } + } + + /** + * Always returns null. + */ + @Override + public QName getQName() { + return null; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/LeafListSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/LeafListSchemaNodeBuilder.java new file mode 100644 index 0000000000..f2ea8cadd0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/LeafListSchemaNodeBuilder.java @@ -0,0 +1,221 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.List; + +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.SchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.TypeAwareBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ConstraintDefinition; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.LeafListSchemaNode; +import org.opendaylight.controller.yang.model.api.MustDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + + +public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, TypeAwareBuilder, MustAwareBuilder, DataSchemaNodeBuilder { + + private final LeafListSchemaNodeImpl instance; + private final QName qname; + private TypeDefinition type; + private MustDefinitionBuilder mustDefinitionBuilder; + + LeafListSchemaNodeBuilder(QName qname) { + this.qname = qname; + instance = new LeafListSchemaNodeImpl(qname); + } + + + @Override + public DataSchemaNode build() { + if(mustDefinitionBuilder != null) { + MustDefinition mustDefinition = mustDefinitionBuilder.build(); + instance.setMustDefinition(mustDefinition); + } + return instance; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public void setPath(SchemaPath path) { + instance.setPath(path); + } + + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + @Override + public TypeDefinition getType() { + return type; + } + + @Override + public void setType(TypeDefinition type) { + this.type = type; + instance.setType(type); + } + + @Override + public void setMustDefinitionBuilder(MustDefinitionBuilder mustDefinitionBuilder) { + this.mustDefinitionBuilder = mustDefinitionBuilder; + } + + public void setAugmenting(boolean augmenting) { + instance.setAugmenting(augmenting); + } + public void setConfiguration(boolean configuration) { + instance.setConfiguration(configuration); + } + public void setConstraints(ConstraintDefinition constraints) { + instance.setConstraints(constraints); + } + public void setUserOrdered(boolean userOrdered) { + instance.setUserOrdered(userOrdered); + } + + + private class LeafListSchemaNodeImpl implements LeafListSchemaNode { + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status = Status.CURRENT; + + private boolean augmenting; + private boolean configuration; + private ConstraintDefinition constraints; + + private TypeDefinition type; + private boolean userOrdered; + + private MustDefinition mustDefinition; + + private LeafListSchemaNodeImpl(QName qname) { + this.qname = qname; + } + + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + private void setPath(SchemaPath path) { + this.path = path;; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + private void setStatus(Status status) { + this.status = status; + } + + @Override + public boolean isAugmenting() { + return augmenting; + } + private void setAugmenting(boolean augmenting) { + this.augmenting = augmenting; + } + + @Override + public boolean isConfiguration() { + return configuration; + } + private void setConfiguration(boolean configuration) { + this.configuration = configuration; + } + + @Override + public ConstraintDefinition getConstraints() { + return constraints; + } + private void setConstraints(ConstraintDefinition constraints) { + this.constraints = constraints; + } + + @Override + public TypeDefinition getType() { + return type; + } + public void setType(TypeDefinition> type) { + this.type = type; + } + + @Override + public boolean isUserOrdered() { + return userOrdered; + } + private void setUserOrdered(boolean userOrdered) { + this.userOrdered = userOrdered; + } + + @Override + public MustDefinition getMustDefinition() { + return mustDefinition; + } + private void setMustDefinition(MustDefinition mustDefinition) { + this.mustDefinition = mustDefinition; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String toString() { + return LeafListSchemaNodeImpl.class.getSimpleName() +"[qname="+ qname +", type="+ type +"]"; + } + } + + } \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/LeafSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/LeafSchemaNodeBuilder.java new file mode 100644 index 0000000000..f50ac8a665 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/LeafSchemaNodeBuilder.java @@ -0,0 +1,232 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.List; + +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.SchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.TypeAwareBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ConstraintDefinition; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.LeafSchemaNode; +import org.opendaylight.controller.yang.model.api.MustDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + + +public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, + SchemaNodeBuilder, TypeAwareBuilder, MustAwareBuilder { + + private final QName qname; + private final LeafSchemaNodeImpl instance; + private TypeDefinition type; + private MustDefinitionBuilder mustDefinitionBuilder; + + LeafSchemaNodeBuilder(QName qname) { + this.qname = qname; + instance = new LeafSchemaNodeImpl(qname); + } + + @Override + public LeafSchemaNode build() { + if (mustDefinitionBuilder != null) { + MustDefinition mustDefinition = mustDefinitionBuilder.build(); + instance.setMustDefinition(mustDefinition); + } + return instance; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public void setPath(SchemaPath path) { + instance.setPath(path); + } + + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + public void setAugmenting(boolean augmenting) { + instance.setAugmenting(augmenting); + } + + public void setConfiguration(boolean configuration) { + instance.setConfiguration(configuration); + } + + public void setConstraints(ConstraintDefinition constraints) { + instance.setConstraints(constraints); + } + + @Override + public TypeDefinition getType() { + return type; + } + + @Override + public void setType(TypeDefinition type) { + this.type = type; + instance.setType(type); + } + + @Override + public void setMustDefinitionBuilder( + MustDefinitionBuilder mustDefinitionBuilder) { + this.mustDefinitionBuilder = mustDefinitionBuilder; + } + + private class LeafSchemaNodeImpl implements LeafSchemaNode { + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status = Status.CURRENT; + + private boolean augmenting; + private boolean configuration; + private ConstraintDefinition constraints; + + private TypeDefinition type; + private MustDefinition mustDefinition; + + private LeafSchemaNodeImpl(QName qname) { + this.qname = qname; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + + private void setPath(SchemaPath path) { + this.path = path; + } + + @Override + public String getDescription() { + return description; + } + + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + + private void setStatus(Status status) { + if (status != null) { + this.status = status; + } + } + + @Override + public boolean isAugmenting() { + return augmenting; + } + + private void setAugmenting(boolean augmenting) { + this.augmenting = augmenting; + } + + @Override + public boolean isConfiguration() { + return configuration; + } + + private void setConfiguration(boolean configuration) { + this.configuration = configuration; + } + + @Override + public ConstraintDefinition getConstraints() { + return constraints; + } + + private void setConstraints(ConstraintDefinition constraints) { + this.constraints = constraints; + } + + @Override + public TypeDefinition getType() { + return type; + } + + private void setType(TypeDefinition> type) { + this.type = type; + } + + @Override + public MustDefinition getMustDefinition() { + return mustDefinition; + } + + private void setMustDefinition(MustDefinition mustDefinition) { + this.mustDefinition = mustDefinition; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( + LeafSchemaNodeImpl.class.getSimpleName()); + sb.append("["); + sb.append("qname=" + qname); + sb.append(", path=" + path); + sb.append(", description=" + description); + sb.append(", reference=" + reference); + sb.append(", status=" + status); + sb.append(", augmenting=" + augmenting); + sb.append(", configuration=" + configuration); + sb.append(", constraints=" + constraints); + sb.append(", type=" + type); + sb.append(", mustDefinition=" + mustDefinition); + sb.append("]"); + return sb.toString(); + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ListSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ListSchemaNodeBuilder.java new file mode 100644 index 0000000000..3059ba91db --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ListSchemaNodeBuilder.java @@ -0,0 +1,463 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.model.parser.api.AbstractChildNodeBuilder; +import org.opendaylight.controller.model.parser.api.AugmentationTargetBuilder; +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.SchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionAwareBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.ConstraintDefinition; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.ListSchemaNode; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +public class ListSchemaNodeBuilder extends AbstractChildNodeBuilder implements DataSchemaNodeBuilder, SchemaNodeBuilder, AugmentationTargetBuilder, TypeDefinitionAwareBuilder { + + private final ListSchemaNodeImpl instance; + + private final Set addedTypedefs = new HashSet(); + private final Set augmentations = new HashSet(); + private final Set usesNodes = new HashSet(); + + ListSchemaNodeBuilder(QName qname) { + super(qname); + instance = new ListSchemaNodeImpl(qname); + } + + @Override + public ListSchemaNode build() { + // CHILD NODES + Map childs = new HashMap(); + for(DataSchemaNodeBuilder node : childNodes) { + childs.put(node.getQName(), node.build()); + } + instance.setChildNodes(childs); + + // TYPEDEFS + Set> typedefs = new HashSet>(); + for (TypeDefinitionBuilder entry : addedTypedefs) { + typedefs.add(entry.build()); + } + instance.setTypeDefinitions(typedefs); + + // USES + Set usesNodeDefinitions = new HashSet(); + for(UsesNodeBuilder builder : usesNodes) { + usesNodeDefinitions.add(builder.build()); + } + instance.setUses(usesNodeDefinitions); + + // GROUPINGS + Set groupingDefinitions = new HashSet(); + for (GroupingBuilder builder : groupings) { + groupingDefinitions.add(builder.build()); + } + instance.setGroupings(groupingDefinitions); + + instance.setAvailableAugmentations(augmentations); + + return instance; + } + + + @Override + public void addTypedef(TypeDefinitionBuilder type) { + addedTypedefs.add(type); + } + + @Override + public void setPath(SchemaPath path) { + instance.setPath(path); + } + + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + @Override + public void addUsesNode(UsesNodeBuilder usesBuilder) { + usesNodes.add(usesBuilder); + } + + @Override + public void addAugmentation(AugmentationSchema augmentationSchema) { + augmentations.add(augmentationSchema); + } + + public void setKeyDefinition(List keyDefinition) { + instance.setKeyDefinition(keyDefinition); + } + public void setAugmenting(boolean augmenting) { + instance.setAugmenting(augmenting); + } + public void setConfiguration(boolean configuration) { + instance.setConfiguration(configuration); + } + public void setConstraints(ConstraintDefinition constraints) { + instance.setConstraints(constraints); + } + public void setUserOrdered(boolean userOrdered) { + instance.setUserOrdered(userOrdered); + } + + + private class ListSchemaNodeImpl implements ListSchemaNode { + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status = Status.CURRENT; + + private List keyDefinition; + + private boolean augmenting; + private boolean configuration; + private ConstraintDefinition constraints; + + private Set augmentations; + + private Map childNodes; + private Set> typeDefinitions; + private Set groupings; + private Set uses; + + private boolean userOrdered; + + private ListSchemaNodeImpl(QName qname) { + this.qname = qname; + } + + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + private void setPath(SchemaPath path) { + this.path = path; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + private void setStatus(Status status) { + this.status = status; + } + + @Override + public List getKeyDefinition() { + return keyDefinition; + } + private void setKeyDefinition(List keyDefinition) { + this.keyDefinition = keyDefinition; + } + + @Override + public boolean isAugmenting() { + return augmenting; + } + private void setAugmenting(boolean augmenting) { + this.augmenting = augmenting; + } + + @Override + public boolean isConfiguration() { + return configuration; + } + private void setConfiguration(boolean configuration) { + this.configuration = configuration; + } + + @Override + public ConstraintDefinition getConstraints() { + return constraints; + } + private void setConstraints(ConstraintDefinition constraints) { + this.constraints = constraints; + } + + @Override + public Set getAvailableAugmentations() { + return augmentations; + } + private void setAvailableAugmentations(Set augmentations) { + this.augmentations = augmentations; + } + + @Override + public Set getChildNodes() { + return new HashSet(childNodes.values()); + } + void setChildNodes(Map childNodes) { + this.childNodes = childNodes; + } + + @Override + public Set getGroupings() { + return groupings; + } + private void setGroupings(Set groupings) { + this.groupings = groupings; + } + + @Override + public Set> getTypeDefinitions() { + return typeDefinitions; + } + private void setTypeDefinitions(Set> typeDefinitions) { + this.typeDefinitions = typeDefinitions; + } + + @Override + public Set getUses() { + return uses; + } + private void setUses(Set uses) { + this.uses = uses; + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + return childNodes.get(name); + } + + @Override + public DataSchemaNode getDataChildByName(String name) { + DataSchemaNode result = null; + for(Map.Entry entry : childNodes.entrySet()) { + if(entry.getKey().getLocalName().equals(name)) { + result = entry.getValue(); + break; + } + } + return result; + } + + @Override + public boolean isUserOrdered() { + return userOrdered; + } + private void setUserOrdered(boolean userOrdered) { + this.userOrdered = userOrdered; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((qname == null) ? 0 : qname.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + ((keyDefinition == null) ? 0 : keyDefinition.hashCode()); + result = prime * result + (augmenting ? 1231 : 1237); + result = prime * result + (configuration ? 1231 : 1237); + result = prime * result + ((constraints == null) ? 0 : constraints.hashCode()); + result = prime * result + ((augmentations == null) ? 0 : augmentations.hashCode()); + result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode()); + result = prime * result + ((typeDefinitions == null) ? 0 : typeDefinitions.hashCode()); + result = prime * result + ((groupings == null) ? 0 : groupings.hashCode()); + result = prime * result + ((uses == null) ? 0 : uses.hashCode()); + result = prime * result + (userOrdered ? 1231 : 1237); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ListSchemaNodeImpl other = (ListSchemaNodeImpl) obj; + if (qname == null) { + if (other.qname != null) { + return false; + } + } else if (!qname.equals(other.qname)) { + return false; + } + if (path == null) { + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (status == null) { + if (other.status != null) { + return false; + } + } else if (!status.equals(other.status)) { + return false; + } + if (keyDefinition == null) { + if (other.keyDefinition != null) { + return false; + } + } else if (!keyDefinition.equals(other.keyDefinition)) { + return false; + } + if(augmenting != other.augmenting) { + return false; + } + if(configuration != other.configuration) { + return false; + } + if (constraints == null) { + if (other.constraints != null) { + return false; + } + } else if (!constraints.equals(other.constraints)) { + return false; + } + if (augmentations == null) { + if (other.augmentations != null) { + return false; + } + } else if (!augmentations.equals(other.augmentations)) { + return false; + } + if (childNodes == null) { + if (other.childNodes != null) { + return false; + } + } else if (!childNodes.equals(other.childNodes)) { + return false; + } + if (typeDefinitions == null) { + if (other.typeDefinitions != null) { + return false; + } + } else if (!typeDefinitions.equals(other.typeDefinitions)) { + return false; + } + if (groupings == null) { + if (other.groupings != null) { + return false; + } + } else if (!groupings.equals(other.groupings)) { + return false; + } + if (uses == null) { + if (other.uses != null) { + return false; + } + } else if (!uses.equals(other.uses)) { + return false; + } + if(userOrdered != other.userOrdered) { + return false; + } + return true; + } + + + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(ListSchemaNodeImpl.class.getSimpleName()); + sb.append("["); + sb.append("qname="+ qname); + sb.append(", path="+ path); + sb.append(", description="+ description); + sb.append(", reference="+ reference); + sb.append(", status="+ status); + sb.append(", keyDefinition="+ keyDefinition); + sb.append(", augmenting="+ augmenting); + sb.append(", configuration="+ configuration); + sb.append(", constraints="+ constraints); + sb.append(", augmentations="+ augmentations); + sb.append(", childNodes="+ childNodes.values()); + sb.append(", typedefinitions="+ typeDefinitions); + sb.append(", groupings="+ groupings); + sb.append(", uses="+ uses); + sb.append(", userOrdered="+ userOrdered); + sb.append("]"); + return sb.toString(); + } + } + + } \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ModuleBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ModuleBuilder.java new file mode 100644 index 0000000000..98cfbb6e16 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/ModuleBuilder.java @@ -0,0 +1,824 @@ +/* + * 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.controller.model.parser.builder; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.opendaylight.controller.model.parser.api.AugmentationSchemaBuilder; +import org.opendaylight.controller.model.parser.api.Builder; +import org.opendaylight.controller.model.parser.api.ChildNodeBuilder; +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.TypeAwareBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionAwareBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.Deviation; +import org.opendaylight.controller.yang.model.api.FeatureDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.ModuleImport; +import org.opendaylight.controller.yang.model.api.NotificationDefinition; +import org.opendaylight.controller.yang.model.api.RpcDefinition; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +/** + * This builder builds Module object. If this module is dependent on external + * module/modules, these dependencies must be resolved before module is built, + * otherwise result may not be valid. + */ +public class ModuleBuilder implements Builder { + + private final ModuleImpl instance; + private final String name; + private String prefix; + + private final Set imports = new HashSet(); + private Set augmentations; + + /** + * All nodes, that can contain other nodes + */ + private final Map, Builder> moduleNodes = new HashMap, Builder>(); + + /** + * Holds all child (DataSchemaNode) nodes: anyxml, choice, container, list, leaf, leaf-list. + */ + private final Map, DataSchemaNodeBuilder> addedChilds = new HashMap, DataSchemaNodeBuilder>(); + + private final Map, GroupingBuilder> addedGroupings = new HashMap, GroupingBuilder>(); + private final Set addedAugments = new HashSet(); + private final Map, UsesNodeBuilder> addedUsesNodes = new HashMap, UsesNodeBuilder>(); + private final Map, RpcDefinitionBuilder> addedRpcs = new HashMap, RpcDefinitionBuilder>(); + private final Set addedNotifications = new HashSet(); + private final Map, FeatureBuilder> addedFeatures = new HashMap, FeatureBuilder>(); + private final Map addedDeviations = new HashMap(); + private final Map, TypeDefinitionBuilder> addedTypedefs = new HashMap, TypeDefinitionBuilder>(); + + + private final Map, TypeAwareBuilder> dirtyNodes = new HashMap, TypeAwareBuilder>(); + + + public ModuleBuilder(String name) { + this.name = name; + instance = new ModuleImpl(name); + } + + /** + * Build new Module object based on this builder. Throws IllegalStateException if builder contains unresolved nodes. + */ + public Module build() { + instance.setImports(imports); + + // TYPEDEFS + Set> typedefs = buildModuleTypedefs(addedTypedefs); + instance.setTypeDefinitions(typedefs); + + // CHILD NODES + final Map childNodes = buildModuleChildNodes(addedChilds); + instance.setChildNodes(childNodes); + + // GROUPINGS + final Set groupings = buildModuleGroupings(addedGroupings); + instance.setGroupings(groupings); + + // USES + final Set usesNodeDefinitions = buildUsesNodes(addedUsesNodes); + instance.setUses(usesNodeDefinitions); + + // FEATURES + Set features = buildModuleFeatures(addedFeatures); + instance.setFeatures(features); + + // NOTIFICATIONS + final Set notifications = new HashSet(); + for (NotificationBuilder entry : addedNotifications) { + notifications.add((NotificationDefinition) entry.build()); + } + instance.setNotifications(notifications); + + // AUGMENTATIONS +// final Set augmentations = new HashSet(); +// for(AugmentationSchemaBuilder entry : addedAugments) { +// augmentations.add(entry.build()); +// } +// instance.setAugmentations(augmentations); + instance.setAugmentations(augmentations); + + // RPCs + final Set rpcs = buildModuleRpcs(addedRpcs); + instance.setRpcs(rpcs); + + // DEVIATIONS + Set deviations = new HashSet(); + for(Map.Entry entry : addedDeviations.entrySet()) { + deviations.add(entry.getValue().build()); + } + instance.setDeviations(deviations); + + return instance; + } + + Builder getNode(List path) { + return moduleNodes.get(path); + } + + Map, TypeAwareBuilder> getDirtyNodes() { + return dirtyNodes; + } + + String getName() { + return name; + } + + String getPrefix() { + return prefix; + } + + Set getAddedAugments() { + return addedAugments; + } + + + public void addDirtyNode(Stack path) { + List dirtyNodePath = new ArrayList(path); + TypeAwareBuilder nodeBuilder = (TypeAwareBuilder)moduleNodes.get(dirtyNodePath); + dirtyNodes.put(dirtyNodePath, nodeBuilder); + } + + public void setNamespace(URI namespace) { + instance.setNamespace(namespace); + } + + public void setRevision(Date revision) { + instance.setRevision(revision); + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + instance.setPrefix(prefix); + } + + public void setYangVersion(String yangVersion) { + instance.setYangVersion(yangVersion); + } + + public void setDescription(String description) { + instance.setDescription(description); + } + public void setReference(String reference) { + instance.setReference(reference); + } + public void setOrganization(String organization) { + instance.setOrganization(organization); + } + public void setContact(String contact) { + instance.setContact(contact); + } + public void setAugmentations(Set augmentations) { + this.augmentations = augmentations; + } + + public boolean addModuleImport(final String moduleName, final Date revision, final String prefix) { + ModuleImport moduleImport = createModuleImport(moduleName, revision, prefix); + return imports.add(moduleImport); + } + + public Set getModuleImports() { + return imports; + } + + public ContainerSchemaNodeBuilder addContainerNode(QName containerName, Stack parentPath) { + List pathToNode = new ArrayList(parentPath); + + ContainerSchemaNodeBuilder containerBuilder = new ContainerSchemaNodeBuilder(containerName); + + ChildNodeBuilder parent = (ChildNodeBuilder)moduleNodes.get(pathToNode); + if(parent != null) { + parent.addChildNode(containerBuilder); + } + + pathToNode.add(containerName.getLocalName()); + moduleNodes.put(pathToNode, containerBuilder); + addedChilds.put(pathToNode, containerBuilder); + + return containerBuilder; + } + + public ListSchemaNodeBuilder addListNode(QName listName, Stack parentPath) { + List pathToNode = new ArrayList(parentPath); + + ListSchemaNodeBuilder listBuilder = new ListSchemaNodeBuilder(listName); + + ChildNodeBuilder parent = (ChildNodeBuilder)moduleNodes.get(pathToNode); + if(parent != null) { + parent.addChildNode(listBuilder); + } + + pathToNode.add(listName.getLocalName()); + moduleNodes.put(pathToNode, listBuilder); + addedChilds.put(pathToNode, listBuilder); + + return listBuilder; + } + + public LeafSchemaNodeBuilder addLeafNode(QName leafName, Stack parentPath) { + List pathToNode = new ArrayList(parentPath); + + LeafSchemaNodeBuilder leafBuilder = new LeafSchemaNodeBuilder(leafName); + + ChildNodeBuilder parent = (ChildNodeBuilder)moduleNodes.get(pathToNode); + if(parent != null) { + parent.addChildNode(leafBuilder); + } + + pathToNode.add(leafName.getLocalName()); + addedChilds.put(pathToNode, leafBuilder); + moduleNodes.put(pathToNode, leafBuilder); + + return leafBuilder; + } + + public LeafListSchemaNodeBuilder addLeafListNode(QName leafListName, Stack parentPath) { + List pathToNode = new ArrayList(parentPath); + + LeafListSchemaNodeBuilder leafListBuilder = new LeafListSchemaNodeBuilder(leafListName); + ChildNodeBuilder parent = (ChildNodeBuilder)moduleNodes.get(pathToNode); + if(parent != null) { + parent.addChildNode(leafListBuilder); + } + + pathToNode.add(leafListName.getLocalName()); + addedChilds.put(pathToNode, leafListBuilder); + moduleNodes.put(pathToNode, leafListBuilder); + + return leafListBuilder; + } + + public GroupingBuilder addGrouping(QName qname, Stack parentPath) { + List pathToGroup = new ArrayList(parentPath); + + GroupingBuilder builder = new GroupingBuilderImpl(qname); + ChildNodeBuilder parentNodeBuilder = (ChildNodeBuilder)moduleNodes.get(pathToGroup); + if(parentNodeBuilder != null) { + parentNodeBuilder.addGrouping(builder); + } + + pathToGroup.add(qname.getLocalName()); + moduleNodes.put(pathToGroup, builder); + addedGroupings.put(pathToGroup, builder); + + return builder; + } + + public AugmentationSchemaBuilder addAugment(String name, Stack parentPath) { + List pathToAugment = new ArrayList(parentPath); + + AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name); + + // augment can only be in 'module' or 'uses' statement + UsesNodeBuilder parent = addedUsesNodes.get(pathToAugment); + if(parent != null) { + parent.addAugment(builder); + } + + pathToAugment.add(name); + moduleNodes.put(pathToAugment, builder); + addedAugments.add(builder); + + return builder; + } + + public UsesNodeBuilder addUsesNode(String groupingPathStr, Stack parentPath) { + List pathToUses = new ArrayList(parentPath); + + UsesNodeBuilder builder = new UsesNodeBuilderImpl(groupingPathStr); + + ChildNodeBuilder parent = (ChildNodeBuilder)moduleNodes.get(pathToUses); + if(parent != null) { + parent.addUsesNode(builder); + } + + pathToUses.add(groupingPathStr); + addedUsesNodes.put(pathToUses, builder); + + return builder; + } + + public RpcDefinitionBuilder addRpc(QName qname, Stack parentPath) { + List pathToRpc = new ArrayList(parentPath); + + RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(qname); + + pathToRpc.add(qname.getLocalName()); + addedRpcs.put(pathToRpc, rpcBuilder); + + QName inputQName = new QName(qname.getNamespace(), qname.getRevision(), qname.getPrefix(), "input"); + ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(inputQName); + List pathToInput = new ArrayList(pathToRpc); + pathToInput.add("input"); + moduleNodes.put(pathToInput, inputBuilder); + rpcBuilder.setInput(inputBuilder); + + QName outputQName = new QName(qname.getNamespace(), qname.getRevision(), qname.getPrefix(), "output"); + ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(outputQName); + List pathToOutput = new ArrayList(pathToRpc); + pathToOutput.add("output"); + moduleNodes.put(pathToOutput, outputBuilder); + rpcBuilder.setOutput(outputBuilder); + + return rpcBuilder; + } + + public NotificationBuilder addNotification(QName notificationName, Stack parentPath) { + List pathToNotification = new ArrayList(parentPath); + + NotificationBuilder notificationBuilder = new NotificationBuilder(notificationName); + + pathToNotification.add(notificationName.getLocalName()); + moduleNodes.put(pathToNotification, notificationBuilder); + addedNotifications.add(notificationBuilder); + + return notificationBuilder; + } + + public FeatureBuilder addFeature(QName featureName, Stack parentPath) { + List pathToFeature = new ArrayList(parentPath); + pathToFeature.add(featureName.getLocalName()); + + FeatureBuilder builder = new FeatureBuilder(featureName); + addedFeatures.put(pathToFeature, builder); + return builder; + } + + public TypedefBuilder addTypedef(QName typeDefName, Stack parentPath) { + List pathToType = new ArrayList(parentPath); + TypedefBuilder builder = new TypedefBuilder(typeDefName); + TypeDefinitionAwareBuilder parent = (TypeDefinitionAwareBuilder)moduleNodes.get(pathToType); + if(parent != null) { + parent.addTypedef(builder); + } + pathToType.add(typeDefName.getLocalName()); + addedTypedefs.put(pathToType, builder); + moduleNodes.put(pathToType, builder); + return builder; + } + + public Set getModuleTypedefs() { + Set typedefs = new HashSet(); + for(Map.Entry, TypeDefinitionBuilder> entry : addedTypedefs.entrySet()) { + if(entry.getKey().size() == 2) { + typedefs.add(entry.getValue()); + } + } + return typedefs; + } + + public void setType(TypeDefinition type, Stack parentPath) { + TypeAwareBuilder parent = (TypeAwareBuilder)moduleNodes.get(parentPath); + parent.setType(type); + } + + public DeviationBuilder addDeviation(String targetPath) { + DeviationBuilder builder = new DeviationBuilder(targetPath); + addedDeviations.put(targetPath, builder); + return builder; + } + + public MustDefinitionBuilder addMustDefinition(String xpathStr, Stack parentPath) { + MustAwareBuilder parent = (MustAwareBuilder)moduleNodes.get(parentPath); + String path = parentPath.get(parentPath.size()-1); + if(parent == null) { + for(Map.Entry db : addedDeviations.entrySet()) { + String key = db.getKey(); + if(key.equals(path)) { + parent = db.getValue(); + } + } + } + MustDefinitionBuilder builder = new MustDefinitionBuilder(xpathStr); + parent.setMustDefinitionBuilder(builder); + return builder; + } + + public ModuleBuilder addSubmodule(QName qname) { + ModuleBuilder submoduleBuilder = new ModuleBuilder(qname.getLocalName()); + return submoduleBuilder; + } + + + + private class ModuleImpl implements Module { + + private URI namespace; + private final String name; + private Date revision; + private String prefix; + private String yangVersion; + private String description; + private String reference; + private String organization; + private String contact; + private Set imports; + private Set features; + private Set> typeDefinitions; + private Set notifications; + private Set augmentations; + private Set rpcs; + private Set deviations; + private Map childNodes; + private Set groupings; + private Set uses; + + private ModuleImpl(String name) { + this.name = name; + } + + + @Override + public URI getNamespace() { + return namespace; + } + private void setNamespace(URI namespace) { + this.namespace = namespace; + } + + @Override + public String getName() { + return name; + } + + @Override + public Date getRevision() { + return revision; + } + private void setRevision(Date revision) { + this.revision = revision; + } + + @Override + public String getPrefix() { + return prefix; + } + private void setPrefix(String prefix) { + this.prefix = prefix; + } + + @Override + public String getYangVersion() { + return yangVersion; + } + private void setYangVersion(String yangVersion) { + this.yangVersion = yangVersion; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public String getOrganization() { + return organization; + } + private void setOrganization(String organization) { + this.organization = organization; + } + + @Override + public String getContact() { + return contact; + } + private void setContact(String contact) { + this.contact = contact; + } + + @Override + public Set getImports() { + return imports; + } + private void setImports(Set imports) { + this.imports = imports; + } + + @Override + public Set getFeatures() { + return features; + } + private void setFeatures(Set features) { + this.features = features; + } + + @Override + public Set> getTypeDefinitions() { + return typeDefinitions; + } + private void setTypeDefinitions(Set> typeDefinitions) { + this.typeDefinitions = typeDefinitions; + } + + @Override + public Set getNotifications() { + return notifications; + } + private void setNotifications(Set notifications) { + this.notifications = notifications; + } + + @Override + public Set getAugmentations() { + return augmentations; + } + private void setAugmentations(Set augmentations) { + this.augmentations = augmentations; + } + + @Override + public Set getRpcs() { + return rpcs; + } + private void setRpcs(Set rpcs) { + this.rpcs = rpcs; + } + + @Override + public Set getDeviations() { + return deviations; + } + private void setDeviations(Set deviations) { + this.deviations = deviations; + } + + @Override + public Set getChildNodes() { + return new HashSet(childNodes.values()); + } + private void setChildNodes(Map childNodes) { + this.childNodes = childNodes; + } + + @Override + public Set getGroupings() { + return groupings; + } + private void setGroupings(Set groupings) { + this.groupings = groupings; + } + + @Override + public Set getUses() { + return uses; + } + private void setUses(Set uses) { + this.uses = uses; + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + return childNodes.get(name); + } + @Override + public DataSchemaNode getDataChildByName(String name) { + DataSchemaNode result = null; + for(Map.Entry entry : childNodes.entrySet()) { + if(entry.getKey().getLocalName().equals(name)) { + result = entry.getValue(); + break; + } + } + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(ModuleImpl.class.getSimpleName()); + sb.append("[\n"); + sb.append("name="+ name +",\n"); + sb.append("namespace="+ namespace +",\n"); + sb.append("revision="+ revision +",\n"); + sb.append("prefix="+ prefix +",\n"); + sb.append("yangVersion="+ yangVersion +",\n"); + sb.append("description="+ description +",\n"); + sb.append("reference="+ reference +",\n"); + sb.append("organization="+ organization +",\n"); + sb.append("contact="+ contact +",\n"); + sb.append("childNodes="+ childNodes.values() +",\n"); + sb.append("groupings="+ groupings +",\n"); + sb.append("imports="+ imports +",\n"); + sb.append("features="+ features +",\n"); + sb.append("typeDefinitions="+ typeDefinitions +",\n"); + sb.append("notifications="+ notifications +",\n"); + sb.append("augmentations="+ augmentations +",\n"); + sb.append("rpcs="+ rpcs +",\n"); + sb.append("deviations="+ deviations +"\n"); + sb.append("]"); + return sb.toString(); + } + + } + + private ModuleImport createModuleImport(final String moduleName, final Date revision, final String prefix) { + ModuleImport moduleImport = new ModuleImport() { + @Override + public String getModuleName() { + return moduleName; + } + @Override + public Date getRevision() { + return revision; + } + @Override + public String getPrefix() { + return prefix; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((moduleName == null) ? 0 : moduleName.hashCode()); + result = prime * result + ((revision == null) ? 0 : revision.hashCode()); + result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ModuleImport other = (ModuleImport) obj; + if (getModuleName() == null) { + if (other.getModuleName() != null) { + return false; + } + } else if (!getModuleName().equals(other.getModuleName())) { + return false; + } + if (getRevision() == null) { + if (other.getRevision() != null) { + return false; + } + } else if (!getRevision().equals(other.getRevision())) { + return false; + } + if (getPrefix() == null) { + if (other.getPrefix() != null) { + return false; + } + } else if (!getPrefix().equals(other.getPrefix())) { + return false; + } + return true; + } + + @Override + public String toString() { + return "ModuleImport[moduleName="+ moduleName +", revision="+ revision +", prefix="+ prefix +"]"; + } + }; + return moduleImport; + } + + /** + * Traverse through given addedChilds and add only direct module childs. Direct + * module child path size is 2 (1. module name, 2. child name). + * + * @param addedChilds + * @return map of children, where key is child QName and value is child itself + */ + private Map buildModuleChildNodes( + Map, DataSchemaNodeBuilder> addedChilds) { + final Map childNodes = new HashMap(); + for (Map.Entry, DataSchemaNodeBuilder> entry : addedChilds + .entrySet()) { + if (entry.getKey().size() == 2) { + DataSchemaNode node = entry.getValue().build(); + QName qname = entry.getValue().getQName(); + childNodes.put(qname, node); + } + } + return childNodes; + } + + /** + * Traverse through given addedGroupings and add only direct module groupings. Direct + * module grouping path size is 2 (1. module name, 2. grouping name). + * + * @param addedGroupings + * @return set of built GroupingDefinition objects + */ + private Set buildModuleGroupings(Map, GroupingBuilder> addedGroupings) { + final Set groupings = new HashSet(); + for(Map.Entry, GroupingBuilder> entry : addedGroupings.entrySet()) { + if(entry.getKey().size() == 2) { + groupings.add(entry.getValue().build()); + } + } + return groupings; + } + + /** + * Traverse through given addedRpcs and build RpcDefinition objects. + * @param addedRpcs + * @return set of built RpcDefinition objects + */ + private Set buildModuleRpcs(Map, RpcDefinitionBuilder> addedRpcs) { + final Set rpcs = new HashSet(); + RpcDefinitionBuilder builder; + for(Map.Entry, RpcDefinitionBuilder> entry : addedRpcs.entrySet()) { + builder = entry.getValue(); + RpcDefinition rpc = builder.build(); + rpcs.add(rpc); + } + return rpcs; + } + + /** + * Traverse through given addedTypedefs and add only direct module typedef statements. Direct + * module typedef path size is 2 (1. module name, 2. typedef name). + * + * @param addedTypedefs + * @return set of built module typedef statements + */ + private Set> buildModuleTypedefs(Map, TypeDefinitionBuilder> addedTypedefs) { + Set> typedefs = new HashSet>(); + for(Map.Entry, TypeDefinitionBuilder> entry : addedTypedefs.entrySet()) { + if(entry.getKey().size() == 2) { + TypeDefinition> node = entry.getValue().build(); + typedefs.add(node); + } + } + return typedefs; + } + + /** + * Traverse through given addedUsesNodes and add only direct module uses nodes. Direct + * module uses node path size is 2 (1. module name, 2. uses name). + * + * @param addedUsesNodes + * @return set of built module uses nodes + */ + private Set buildUsesNodes(Map, UsesNodeBuilder> addedUsesNodes) { + final Set usesNodeDefinitions = new HashSet(); + for (Map.Entry, UsesNodeBuilder> entry : addedUsesNodes.entrySet()) { + if (entry.getKey().size() == 2) { + usesNodeDefinitions.add(entry.getValue().build()); + } + } + return usesNodeDefinitions; + } + + /** + * Traverse through given addedFeatures and add only direct module features. Direct + * module feature path size is 2 (1. module name, 2. feature name). + * + * @param addedFeatures + * @return set of built module features + */ + private Set buildModuleFeatures(Map, FeatureBuilder> addedFeatures) { + Set features = new HashSet(); + for(Map.Entry, FeatureBuilder> entry : addedFeatures.entrySet()) { + if(entry.getKey().size() == 2) { + features.add((FeatureDefinition)entry.getValue().build()); + } + } + return features; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/MustAwareBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/MustAwareBuilder.java new file mode 100644 index 0000000000..4798590fb9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/MustAwareBuilder.java @@ -0,0 +1,17 @@ +/* + * 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.controller.model.parser.builder; + +/** + * Interface for all nodes which can contain 'must' definition: [container, leaf, leaf-list, list, anyxml, deviate] + */ +public interface MustAwareBuilder { + + void setMustDefinitionBuilder(MustDefinitionBuilder mustDefinitionBuilder); + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/MustDefinitionBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/MustDefinitionBuilder.java new file mode 100644 index 0000000000..fecfae8020 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/MustDefinitionBuilder.java @@ -0,0 +1,86 @@ +/* + * 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.controller.model.parser.builder; + +import org.opendaylight.controller.model.parser.api.Builder; +import org.opendaylight.controller.yang.model.api.MustDefinition; +import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; + + +public class MustDefinitionBuilder implements Builder { + + private final MustDefinitionImpl instance; + + MustDefinitionBuilder(String xpathStr) { + instance = new MustDefinitionImpl(xpathStr); + } + + @Override + public MustDefinition build() { + return instance; + } + + public void setDescription(String description) { + instance.setDescription(description); + } + + public void setReference(String reference) { + instance.setReference(reference); + } + + private static class MustDefinitionImpl implements MustDefinition { + + private final String xpathStr; + private String description; + private String reference; + + private MustDefinitionImpl(String xpathStr) { + this.xpathStr = xpathStr; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getErrorAppTag() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getErrorMessage() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public RevisionAwareXPath getXpath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String toString() { + return MustDefinitionImpl.class.getSimpleName() +"[xpathStr="+ xpathStr +"]"; + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/NotificationBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/NotificationBuilder.java new file mode 100644 index 0000000000..52decc0645 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/NotificationBuilder.java @@ -0,0 +1,229 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.model.parser.api.AbstractChildNodeBuilder; +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.SchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionAwareBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.NotificationDefinition; +import org.opendaylight.controller.yang.model.api.SchemaNode; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +public class NotificationBuilder extends AbstractChildNodeBuilder implements TypeDefinitionAwareBuilder, SchemaNodeBuilder { + + private final NotificationDefinitionImpl instance; + private final Set addedTypedefs = new HashSet(); + private final Set addedUsesNodes = new HashSet(); + + NotificationBuilder(QName qname) { + super(qname); + instance = new NotificationDefinitionImpl(qname); + } + + @Override + public SchemaNode build() { + // CHILD NODES + Map childs = new HashMap(); + for (DataSchemaNodeBuilder node : childNodes) { + childs.put(node.getQName(), node.build()); + } + instance.setChildNodes(childs); + + // GROUPINGS + Set groupingDefinitions = new HashSet(); + for (GroupingBuilder builder : groupings) { + groupingDefinitions.add(builder.build()); + } + instance.setGroupings(groupingDefinitions); + + // TYPEDEFS + Set> typedefs = new HashSet>(); + for (TypeDefinitionBuilder entry : addedTypedefs) { + typedefs.add(entry.build()); + } + instance.setTypeDefinitions(typedefs); + + // USES + Set uses = new HashSet(); + for (UsesNodeBuilder builder : addedUsesNodes) { + uses.add(builder.build()); + } + instance.setUses(uses); + + return instance; + } + + @Override + public void addTypedef(TypeDefinitionBuilder type) { + addedTypedefs.add(type); + } + + @Override + public void addUsesNode(UsesNodeBuilder usesNodeBuilder) { + addedUsesNodes.add(usesNodeBuilder); + } + + @Override + public void setPath(SchemaPath schemaPath) { + instance.setPath(schemaPath); + } + + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + + private class NotificationDefinitionImpl implements NotificationDefinition { + + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status; + + private Map childNodes; + private Set groupings; + private Set> typeDefinitions; + + private Set uses; + + private NotificationDefinitionImpl(QName qname) { + this.qname = qname; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + private void setPath(SchemaPath path) { + this.path = path; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + private void setStatus(Status status) { + this.status = status; + } + + @Override + public Set getChildNodes() { + return new HashSet(childNodes.values()); + } + private void setChildNodes(Map childNodes) { + this.childNodes = childNodes; + } + + @Override + public Set getGroupings() { + return groupings; + } + private void setGroupings(Set groupings) { + this.groupings = groupings; + } + + @Override + public Set getUses() { + return uses; + } + private void setUses(Set uses) { + this.uses = uses; + } + + @Override + public Set> getTypeDefinitions() { + return typeDefinitions; + } + private void setTypeDefinitions(Set> typeDefinitions) { + this.typeDefinitions = typeDefinitions; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + return childNodes.get(name); + } + + @Override + public DataSchemaNode getDataChildByName(String name) { + DataSchemaNode result = null; + for (Map.Entry entry : childNodes.entrySet()) { + if (entry.getKey().getLocalName().equals(name)) { + result = entry.getValue(); + break; + } + } + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( + NotificationDefinitionImpl.class.getSimpleName()); + sb.append("[qname=" + qname + "]"); + return sb.toString(); + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/RpcDefinitionBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/RpcDefinitionBuilder.java new file mode 100644 index 0000000000..55f361b26a --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/RpcDefinitionBuilder.java @@ -0,0 +1,264 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.opendaylight.controller.model.parser.api.ChildNodeBuilder; +import org.opendaylight.controller.model.parser.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.SchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionAwareBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.RpcDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public class RpcDefinitionBuilder implements ChildNodeBuilder, + SchemaNodeBuilder, TypeDefinitionAwareBuilder { + + private final RpcDefinitionImpl instance; + private final QName qname; + private ContainerSchemaNodeBuilder inputBuilder; + private ContainerSchemaNodeBuilder outputBuilder; + private final Set addedTypedefs = new HashSet(); + private final Set addedGroupings = new HashSet(); + + RpcDefinitionBuilder(QName qname) { + this.qname = qname; + this.instance = new RpcDefinitionImpl(qname); + } + + @Override + public RpcDefinition build() { + final ContainerSchemaNode input = inputBuilder.build(); + final ContainerSchemaNode output = outputBuilder.build(); + instance.setInput(input); + instance.setOutput(output); + + // TYPEDEFS + Set> typedefs = new HashSet>(); + for (TypeDefinitionBuilder entry : addedTypedefs) { + typedefs.add(entry.build()); + } + instance.setTypeDefinitions(typedefs); + + // GROUPINGS + final Set groupings = new HashSet(); + for (GroupingBuilder entry : addedGroupings) { + groupings.add(entry.build()); + } + instance.setGroupings(groupings); + + return instance; + } + + void setInput(ContainerSchemaNodeBuilder inputBuilder) { + this.inputBuilder = inputBuilder; + } + + void setOutput(ContainerSchemaNodeBuilder outputBuilder) { + this.outputBuilder = outputBuilder; + } + + @Override + public void addTypedef(TypeDefinitionBuilder type) { + addedTypedefs.add(type); + } + + @Override + public void setPath(SchemaPath schemaPath) { + instance.setPath(schemaPath); + } + + @Override + public void setDescription(String description) { + instance.setDescription(description); + } + + @Override + public void setReference(String reference) { + instance.setReference(reference); + } + + @Override + public void setStatus(Status status) { + instance.setStatus(status); + } + + @Override + public QName getQName() { + return null; + } + + @Override + public void addChildNode(DataSchemaNodeBuilder childNode) { + throw new UnsupportedOperationException( + "Can not add child node to rpc definition: rpc can not contains child nodes."); + } + + @Override + public void addGrouping(GroupingBuilder grouping) { + addedGroupings.add(grouping); + } + + @Override + public void addUsesNode(UsesNodeBuilder usesBuilder) { + throw new UnsupportedOperationException( + "Can not add uses node to rpc definition: rpc can not contains uses nodes."); + } + + @Override + public int hashCode() { + return qname.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof RpcDefinitionBuilder)) { + return false; + } + RpcDefinitionBuilder other = (RpcDefinitionBuilder) obj; + if (other.qname == null) { + if (this.qname != null) { + return false; + } + } else if (!other.qname.equals(this.qname)) { + return false; + } + return true; + } + + private static class RpcDefinitionImpl implements RpcDefinition { + + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status; + + private ContainerSchemaNode input; + private ContainerSchemaNode output; + + private Set> typeDefinitions; + private Set groupings; + + private RpcDefinitionImpl(QName qname) { + this.qname = qname; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + + private void setPath(SchemaPath path) { + this.path = path; + } + + @Override + public String getDescription() { + return description; + } + + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + + private void setStatus(Status status) { + this.status = status; + } + + @Override + public ContainerSchemaNode getInput() { + return input; + } + + private void setInput(ContainerSchemaNode input) { + this.input = input; + } + + @Override + public ContainerSchemaNode getOutput() { + return output; + } + + private void setOutput(ContainerSchemaNode output) { + this.output = output; + } + + @Override + public Set> getTypeDefinitions() { + return typeDefinitions; + } + + private void setTypeDefinitions(Set> typeDefinitions) { + this.typeDefinitions = typeDefinitions; + } + + @Override + public Set getGroupings() { + return groupings; + } + + private void setGroupings(Set groupings) { + this.groupings = groupings; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( + RpcDefinitionImpl.class.getSimpleName() + "["); + sb.append("qname=" + qname); + sb.append(", path=" + path); + sb.append(", description=" + description); + sb.append(", reference=" + reference); + sb.append(", status=" + status); + sb.append(", input=" + input); + sb.append(", output=" + output + "]"); + return sb.toString(); + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/TypedefBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/TypedefBuilder.java new file mode 100644 index 0000000000..a6a3c609cf --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/TypedefBuilder.java @@ -0,0 +1,196 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.List; + +import org.opendaylight.controller.model.parser.api.SchemaNodeBuilder; +import org.opendaylight.controller.model.parser.api.TypeAwareBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.util.UnknownType; +import org.opendaylight.controller.model.util.YangTypesConverter; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + + +public class TypedefBuilder implements TypeDefinitionBuilder, SchemaNodeBuilder, TypeAwareBuilder { + + private final QName qname; + private SchemaPath schemaPath; + private TypeDefinition baseType; + + private String description; + private String reference; + private Status status; + + TypedefBuilder(QName qname) { + this.qname = qname; + } + + @Override + public TypeDefinition> build() { + final TypeDefinition type = YangTypesConverter.javaTypeForBaseYangType(qname); + if(type != null) { + return type; + } else { + if(baseType != null) { + // typedef + TypeDefinitionImpl instance = new TypeDefinitionImpl(qname); + instance.setDescription(description); + instance.setReference(reference); + instance.setStatus(status); + instance.setPath(schemaPath); + instance.setBaseType(baseType); + return instance; + } else { + // type + final UnknownType.Builder unknownBuilder = new UnknownType.Builder(qname, description, reference); + unknownBuilder.status(status); + return unknownBuilder.build(); + } + } + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public void setPath(final SchemaPath schemaPath) { + this.schemaPath = schemaPath; + } + + @Override + public void setDescription(final String description) { + this.description = description; + } + + @Override + public void setReference(final String reference) { + this.reference = reference; + } + + @Override + public void setStatus(final Status status) { + if(status != null) { + this.status = status; + } + } + + @Override + public TypeDefinition getType() { + return baseType; + } + + @Override + public void setType(TypeDefinition baseType) { + this.baseType = baseType; + } + + @Override + public TypeDefinition getBaseType() { + return baseType; + } + + + + private static class TypeDefinitionImpl> implements TypeDefinition { + + private final QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status = Status.CURRENT; + private T baseType; + + private TypeDefinitionImpl(QName qname) { + this.qname = qname; + } + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + private void setPath(SchemaPath path) { + this.path = path; + } + + @Override + public String getDescription() { + return description; + } + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public Status getStatus() { + return status; + } + private void setStatus(Status status) { + this.status = status; + } + + @Override + public T getBaseType() { + return baseType; + } + private void setBaseType(T type) { + this.baseType = type; + } + + @Override + public String getUnits() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object getDefaultValue() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(TypeDefinitionImpl.class.getSimpleName()); + sb.append("["); + sb.append("qname="+ qname); + sb.append(", path="+ path); + sb.append(", description="+ description); + sb.append(", reference="+ reference); + sb.append(", status="+ status); + sb.append(", baseType="+ baseType +"]"); + return sb.toString(); + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/UsesNodeBuilderImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/UsesNodeBuilderImpl.java new file mode 100644 index 0000000000..df626f145f --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/UsesNodeBuilderImpl.java @@ -0,0 +1,78 @@ +/* + * 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.controller.model.parser.builder; + +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.controller.model.parser.api.AugmentationSchemaBuilder; +import org.opendaylight.controller.model.parser.api.Builder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.UsesNode; + +public class UsesNodeBuilderImpl implements UsesNodeBuilder, Builder { + + private final String groupingPathStr; + + UsesNodeBuilderImpl(String groupingPathStr) { + this.groupingPathStr = groupingPathStr; + } + + @Override + public UsesNode build() { + SchemaPath groupingPath = parseUsesPath(groupingPathStr); + final UsesNodeImpl instance = new UsesNodeImpl(groupingPath); + return instance; + } + + public void addAugment(AugmentationSchemaBuilder augmentBuilder) { + // TODO: + } + + private SchemaPath parseUsesPath(String augmentPath) { + String[] splittedPath = augmentPath.split("/"); + List path = new ArrayList(); + QName name; + for (String pathElement : splittedPath) { + String[] splittedElement = pathElement.split(":"); + if (splittedElement.length == 1) { + name = new QName(null, null, null, splittedElement[0]); + } else { + name = new QName(null, null, splittedElement[0], + splittedElement[1]); + } + path.add(name); + } + // TODO: absolute vs relative? + return new SchemaPath(path, false); + } + + private static class UsesNodeImpl implements UsesNode { + + private final SchemaPath groupingPath; + + private UsesNodeImpl(SchemaPath groupingPath) { + this.groupingPath = groupingPath; + } + + @Override + public SchemaPath getGroupingPath() { + return groupingPath; + } + + @Override + public String toString() { + return UsesNodeImpl.class.getSimpleName() + "[groupingPath=" + + groupingPath + "]"; + } + + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/YangModelBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/YangModelBuilder.java new file mode 100644 index 0000000000..bc0f36372b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/builder/YangModelBuilder.java @@ -0,0 +1,198 @@ +/* + * 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.controller.model.parser.builder; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.opendaylight.controller.antlrv4.code.gen.YangLexer; +import org.opendaylight.controller.antlrv4.code.gen.YangParser; +import org.opendaylight.controller.model.parser.api.AugmentationSchemaBuilder; +import org.opendaylight.controller.model.parser.api.AugmentationTargetBuilder; +import org.opendaylight.controller.model.parser.api.Builder; +import org.opendaylight.controller.model.parser.api.TypeAwareBuilder; +import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder; +import org.opendaylight.controller.model.parser.impl.YangModelParserImpl; +import org.opendaylight.controller.model.util.UnknownType; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.ModuleImport; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class YangModelBuilder implements Builder { + + private static final Logger logger = LoggerFactory + .getLogger(YangModelBuilder.class); + + private final Map modules = new HashMap(); + + public YangModelBuilder(String... yangFiles) { + final YangModelParserImpl yangModelParser = new YangModelParserImpl(); + final ParseTreeWalker walker = new ParseTreeWalker(); + + List trees = parseYangFiles(yangFiles); + + ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; + + for (int i = 0; i < trees.size(); i++) { + walker.walk(yangModelParser, trees.get(i)); + builders[i] = yangModelParser.getModuleBuilder(); + } + + for (ModuleBuilder builder : builders) { + final String builderName = builder.getName(); + modules.put(builderName, builder); + } + } + + @Override + public Map build() { + Map builtModules = new HashMap(); + for (ModuleBuilder builder : modules.values()) { + validateBuilder(builder); + builtModules.put(builder.getName(), builder.build()); + } + return builtModules; + } + + private void validateBuilder(ModuleBuilder builder) { + resolveTypedefs(builder); + resolveAugments(builder); + } + + private void resolveTypedefs(ModuleBuilder builder) { + Map, TypeAwareBuilder> dirtyNodes = builder + .getDirtyNodes(); + if (dirtyNodes.size() == 0) { + return; + } else { + for (Map.Entry, TypeAwareBuilder> entry : dirtyNodes + .entrySet()) { + TypeAwareBuilder tab = entry.getValue(); + TypeDefinitionBuilder tdb = findTypeAwareBuilder( + entry.getValue(), builder); + tab.setType(tdb.build()); + } + } + } + + private TypeDefinitionBuilder findTypeAwareBuilder( + TypeAwareBuilder typeBuilder, ModuleBuilder builder) { + UnknownType type = (UnknownType) typeBuilder.getType(); + QName typeQName = type.getQName(); + String typeName = type.getQName().getLocalName(); + String prefix = typeQName.getPrefix(); + + ModuleBuilder dependentModuleBuilder; + if (prefix.equals(builder.getPrefix())) { + dependentModuleBuilder = builder; + } else { + String dependentModuleName = getDependentModuleName(builder, prefix); + dependentModuleBuilder = modules.get(dependentModuleName); + } + + Set typedefs = dependentModuleBuilder + .getModuleTypedefs(); + + TypeDefinitionBuilder lookedUpBuilder = null; + for (TypeDefinitionBuilder tdb : typedefs) { + QName qname = tdb.getQName(); + if (qname.getLocalName().equals(typeName)) { + lookedUpBuilder = tdb; + break; + } + } + + if (lookedUpBuilder.getBaseType() instanceof UnknownType) { + return findTypeAwareBuilder((TypeAwareBuilder) lookedUpBuilder, + dependentModuleBuilder); + } else { + return lookedUpBuilder; + } + } + + private void resolveAugments(ModuleBuilder builder) { + Set augmentBuilders = builder + .getAddedAugments(); + + Set augments = new HashSet(); + for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) { + SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath(); + String prefix = null; + List augmentTargetPath = new ArrayList(); + for (QName pathPart : augmentTargetSchemaPath.getPath()) { + prefix = pathPart.getPrefix(); + augmentTargetPath.add(pathPart.getLocalName()); + } + String dependentModuleName = getDependentModuleName(builder, prefix); + augmentTargetPath.add(0, dependentModuleName); + + ModuleBuilder dependentModule = modules.get(dependentModuleName); + AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule + .getNode(augmentTargetPath); + AugmentationSchema result = augmentBuilder.build(); + augmentTarget.addAugmentation(result); + augments.add(result); + } + builder.setAugmentations(augments); + } + + private List parseYangFiles(String... yangFiles) { + List trees = new ArrayList(); + File yangFile; + for (String fileName : yangFiles) { + try { + yangFile = new File(fileName); + FileInputStream inStream = new FileInputStream(yangFile); + ANTLRInputStream input = new ANTLRInputStream(inStream); + final YangLexer lexer = new YangLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final YangParser parser = new YangParser(tokens); + trees.add(parser.yang()); + } catch (IOException e) { + logger.warn("Exception while reading yang file: " + fileName, e); + } + } + return trees; + } + + /** + * Returns name of dependent module based on given prefix. + * + * @param builder + * current builder which contains import + * @param prefix + * prefix of dependent module used in current builder + * @return name of dependent module + */ + private String getDependentModuleName(ModuleBuilder builder, String prefix) { + ModuleImport moduleImport = null; + for (ModuleImport mi : builder.getModuleImports()) { + if (mi.getPrefix().equals(prefix)) { + moduleImport = mi; + break; + } + } + return moduleImport.getModuleName(); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/impl/YangModelParserImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/impl/YangModelParserImpl.java new file mode 100644 index 0000000000..7b121bdebc --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/impl/YangModelParserImpl.java @@ -0,0 +1,703 @@ +/* + * 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.controller.model.parser.impl; + +import static org.opendaylight.controller.model.parser.util.YangModelBuilderHelper.*; + +import java.net.URI; +import java.net.URISyntaxException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Stack; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.opendaylight.controller.antlrv4.code.gen.YangParser; +import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_not_supported_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_replace_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_list_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Presence_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext; +import org.opendaylight.controller.model.api.type.EnumTypeDefinition; +import org.opendaylight.controller.model.api.type.LengthConstraint; +import org.opendaylight.controller.model.api.type.PatternConstraint; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.model.parser.api.AugmentationSchemaBuilder; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.builder.ContainerSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.builder.DeviationBuilder; +import org.opendaylight.controller.model.parser.builder.FeatureBuilder; +import org.opendaylight.controller.model.parser.builder.LeafListSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.builder.LeafSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.builder.ListSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.builder.ModuleBuilder; +import org.opendaylight.controller.model.parser.builder.MustDefinitionBuilder; +import org.opendaylight.controller.model.parser.builder.NotificationBuilder; +import org.opendaylight.controller.model.parser.builder.RpcDefinitionBuilder; +import org.opendaylight.controller.model.parser.builder.TypedefBuilder; +import org.opendaylight.controller.model.parser.util.YangModelBuilderHelper; +import org.opendaylight.controller.model.util.BitsType; +import org.opendaylight.controller.model.util.EnumerationType; +import org.opendaylight.controller.model.util.Leafref; +import org.opendaylight.controller.model.util.StringType; +import org.opendaylight.controller.model.util.YangTypesConverter; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class YangModelParserImpl extends YangParserBaseListener { + + private static final Logger logger = LoggerFactory + .getLogger(YangModelParserImpl.class); + + private ModuleBuilder moduleBuilder; + + private String moduleName; + private URI namespace; + private String yangModelPrefix; + private Date revision; + + private final DateFormat simpleDateFormat = new SimpleDateFormat( + "yyyy-mm-dd"); + private final Stack actualPath = new Stack(); + + @Override + public void enterModule_stmt(YangParser.Module_stmtContext ctx) { + moduleName = stringFromNode(ctx); + actualPath.push(moduleName); + moduleBuilder = new ModuleBuilder(moduleName); + } + + @Override + public void exitModule_stmt(YangParser.Module_stmtContext ctx) { + final String moduleName = actualPath.pop(); + logger.debug("Exiting module " + moduleName); + } + + @Override + public void enterModule_header_stmts(final Module_header_stmtsContext ctx) { + super.enterModule_header_stmts(ctx); + + for (int i = 0; i < ctx.getChildCount(); ++i) { + final ParseTree treeNode = ctx.getChild(i); + if (treeNode instanceof Namespace_stmtContext) { + String namespaceStr = stringFromNode(treeNode); + try { + this.namespace = new URI(namespaceStr); + moduleBuilder.setNamespace(namespace); + } catch (URISyntaxException e) { + logger.warn("Failed to parse module namespace", e); + } + } else if (treeNode instanceof Prefix_stmtContext) { + yangModelPrefix = stringFromNode(treeNode); + moduleBuilder.setPrefix(yangModelPrefix); + } else if (treeNode instanceof Yang_version_stmtContext) { + final String yangVersion = stringFromNode(treeNode); + moduleBuilder.setYangVersion(yangVersion); + } + } + } + + // TODO: resolve submodule parsing + @Override + public void enterSubmodule_header_stmts( + YangParser.Submodule_header_stmtsContext ctx) { + String submoduleName = stringFromNode(ctx); + QName submoduleQName = new QName(namespace, revision, yangModelPrefix, + submoduleName); + moduleBuilder.addSubmodule(submoduleQName); + updatePath(submoduleName); + } + + @Override + public void exitSubmodule_header_stmts( + YangParser.Submodule_header_stmtsContext ctx) { + final String submodule = actualPath.pop(); + logger.debug("exiting submodule " + submodule); + } + + @Override + public void enterOrganization_stmt(YangParser.Organization_stmtContext ctx) { + final String organization = stringFromNode(ctx); + moduleBuilder.setOrganization(organization); + } + + @Override + public void enterContact_stmt(YangParser.Contact_stmtContext ctx) { + String contact = stringFromNode(ctx); + moduleBuilder.setContact(contact); + } + + @Override + public void enterRevision_stmts(Revision_stmtsContext ctx) { + for (int i = 0; i < ctx.getChildCount(); ++i) { + final ParseTree treeNode = ctx.getChild(i); + if (treeNode instanceof Revision_stmtContext) { + final String revisionDateStr = stringFromNode(treeNode); + try { + revision = simpleDateFormat.parse(revisionDateStr); + } catch (ParseException e) { + logger.warn("Failed to parse revision string: " + + revisionDateStr); + } + } + } + } + + @Override + public void enterDescription_stmt(YangParser.Description_stmtContext ctx) { + // if this is module description... + if (actualPath.size() == 1) { + moduleBuilder.setDescription(stringFromNode(ctx)); + } + } + + @Override + public void enterImport_stmt(Import_stmtContext ctx) { + super.enterImport_stmt(ctx); + + final String importName = stringFromNode(ctx); + String importPrefix = null; + Date importRevision = null; + + for (int i = 0; i < ctx.getChildCount(); ++i) { + final ParseTree treeNode = ctx.getChild(i); + if (treeNode instanceof Prefix_stmtContext) { + importPrefix = stringFromNode(treeNode); + } + if (treeNode instanceof Revision_date_stmtContext) { + String importRevisionStr = stringFromNode(treeNode); + try { + importRevision = simpleDateFormat.parse(importRevisionStr); + } catch (Exception e) { + logger.warn("Failed to parse import revision-date.", e); + } + } + } + moduleBuilder.addModuleImport(importName, importRevision, importPrefix); + } + + @Override + public void enterAugment_stmt(YangParser.Augment_stmtContext ctx) { + final String augmentPath = stringFromNode(ctx); + AugmentationSchemaBuilder builder = moduleBuilder.addAugment( + augmentPath, actualPath); + updatePath(augmentPath); + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + String desc = stringFromNode(child); + builder.setDescription(desc); + } else if (child instanceof Reference_stmtContext) { + String ref = stringFromNode(child); + builder.setReference(ref); + } else if (child instanceof Status_stmtContext) { + Status status = getStatus((Status_stmtContext) child); + builder.setStatus(status); + } + } + } + + @Override + public void exitAugment_stmt(YangParser.Augment_stmtContext ctx) { + final String augment = actualPath.pop(); + logger.debug("exiting augment " + augment); + } + + @Override + public void enterMust_stmt(YangParser.Must_stmtContext ctx) { + String mustText = ""; + String description = null; + String reference = null; + for (int i = 0; i < ctx.getChildCount(); ++i) { + ParseTree child = ctx.getChild(i); + if (child instanceof StringContext) { + final StringContext context = (StringContext) child; + for (int j = 0; j < context.getChildCount(); j++) { + String mustPart = context.getChild(j).getText(); + if (j == 0) { + mustText += mustPart + .substring(0, mustPart.length() - 1); + continue; + } + if (j % 2 == 0) { + mustText += mustPart.substring(1); + } + } + } else if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } + } + MustDefinitionBuilder builder = moduleBuilder.addMustDefinition( + mustText, actualPath); + builder.setDescription(description); + builder.setReference(reference); + } + + @Override + public void enterTypedef_stmt(YangParser.Typedef_stmtContext ctx) { + String typedefName = stringFromNode(ctx); + QName typedefQName = new QName(namespace, revision, yangModelPrefix, + typedefName); + TypedefBuilder builder = moduleBuilder.addTypedef(typedefQName, + actualPath); + updatePath(typedefName); + + builder.setPath(getActualSchemaPath(actualPath, namespace, revision, + yangModelPrefix)); + parseSchemaNodeArgs(ctx, builder); + } + + @Override + public void exitTypedef_stmt(YangParser.Typedef_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterType_stmt(YangParser.Type_stmtContext ctx) { + String typeName = stringFromNode(ctx); + QName typeQName; + if (typeName.contains(":")) { + String[] splittedName = typeName.split(":"); + // if this type contains prefix, it means that it point to type in + // external module + typeQName = new QName(null, null, splittedName[0], splittedName[1]); + } else { + typeQName = new QName(namespace, revision, yangModelPrefix, + typeName); + } + + TypeDefinition type = null; + + if (!YangTypesConverter.isBaseYangType(typeName)) { + if (typeName.equals("leafref")) { + // TODO: RevisionAwareXPath implementation + type = new Leafref(new RevisionAwareXPath() { + }); + } else { + type = parseUnknownType(typeQName, ctx); + // mark parent node of this type statement as dirty + moduleBuilder.addDirtyNode(actualPath); + } + } else { + + Type_body_stmtsContext typeBody = null; + for (int i = 0; i < ctx.getChildCount(); i++) { + if (ctx.getChild(i) instanceof Type_body_stmtsContext) { + typeBody = (Type_body_stmtsContext) ctx.getChild(i); + break; + } + } + + if (typeBody == null) { + // if there are no constraints, just grab default base yang type + type = YangTypesConverter.javaTypeForBaseYangType(typeName); + } else { + List rangeStatements = getRangeConstraints(typeBody); + Integer fractionDigits = getFractionDigits(typeBody); + List lengthStatements = getLengthConstraints(typeBody); + List patternStatements = getPatternConstraint(typeBody); + List enumConstants = YangModelBuilderHelper + .getEnumConstants(typeBody); + + if (typeName.equals("decimal64")) { + type = YangTypesConverter.javaTypeForBaseYangDecimal64Type( + rangeStatements, fractionDigits); + } else if (typeName.startsWith("int") + || typeName.startsWith("uint")) { + type = YangTypesConverter.javaTypeForBaseYangIntegerType( + typeName, rangeStatements); + } else if (typeName.equals("enumeration")) { + type = new EnumerationType(enumConstants); + } else if (typeName.equals("string")) { + type = new StringType(lengthStatements, patternStatements); + } else if (typeName.equals("bits")) { + type = new BitsType(getBits(typeBody, actualPath, + namespace, revision, yangModelPrefix)); + } else { + // TODO: implement binary + instance-identifier types + } + } + + } + + moduleBuilder.setType(type, actualPath); + updatePath(typeName); + } + + @Override + public void exitType_stmt(YangParser.Type_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterGrouping_stmt(YangParser.Grouping_stmtContext ctx) { + final String groupName = stringFromNode(ctx); + QName groupQName = new QName(namespace, revision, yangModelPrefix, + groupName); + GroupingBuilder groupBuilder = moduleBuilder.addGrouping(groupQName, + actualPath); + updatePath("grouping"); + updatePath(groupName); + parseSchemaNodeArgs(ctx, groupBuilder); + } + + @Override + public void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx) { + String actContainer = actualPath.pop(); + actContainer += "-" + actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterContainer_stmt(Container_stmtContext ctx) { + super.enterContainer_stmt(ctx); + String containerName = stringFromNode(ctx); + QName containerQName = new QName(namespace, revision, yangModelPrefix, + containerName); + ContainerSchemaNodeBuilder containerBuilder = moduleBuilder + .addContainerNode(containerQName, actualPath); + updatePath(containerName); + + containerBuilder.setPath(getActualSchemaPath(actualPath, namespace, + revision, yangModelPrefix)); + parseSchemaNodeArgs(ctx, containerBuilder); + + for (int i = 0; i < ctx.getChildCount(); ++i) { + final ParseTree childNode = ctx.getChild(i); + if (childNode instanceof Presence_stmtContext) { + containerBuilder.setPresenceContainer(true); + } else if (childNode instanceof Config_stmtContext) { + for (int j = 0; j < childNode.getChildCount(); j++) { + ParseTree configArg = childNode.getChild(j); + if (configArg instanceof Config_argContext) { + String config = stringFromNode(configArg); + if (config.equals("true")) { + containerBuilder.setConfiguration(true); + } else { + containerBuilder.setConfiguration(false); + } + } + } + } + } + } + + @Override + public void exitContainer_stmt(Container_stmtContext ctx) { + super.exitContainer_stmt(ctx); + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + private boolean isLeafReadOnly(final ParseTree leaf) { + if (leaf != null) { + for (int i = 0; i < leaf.getChildCount(); ++i) { + final ParseTree configContext = leaf.getChild(i); + if (configContext instanceof Config_argContext) { + final String value = stringFromNode(configContext); + if (value.equals("true")) { + return true; + } + } + } + } + return false; + } + + @Override + public void enterLeaf_stmt(Leaf_stmtContext ctx) { + super.enterLeaf_stmt(ctx); + + final String leafName = stringFromNode(ctx); + QName leafQName = new QName(namespace, revision, yangModelPrefix, + leafName); + LeafSchemaNodeBuilder leafBuilder = moduleBuilder.addLeafNode( + leafQName, actualPath); + updatePath(leafName); + + leafBuilder.setPath(getActualSchemaPath(actualPath, namespace, + revision, yangModelPrefix)); + parseSchemaNodeArgs(ctx, leafBuilder); + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Config_stmtContext) { + leafBuilder.setConfiguration(isLeafReadOnly(child)); + } + } + } + + @Override + public void exitLeaf_stmt(YangParser.Leaf_stmtContext ctx) { + final String actLeaf = actualPath.pop(); + logger.debug("exiting " + actLeaf); + } + + @Override + public void enterUses_stmt(YangParser.Uses_stmtContext ctx) { + final String groupingPathStr = stringFromNode(ctx); + moduleBuilder.addUsesNode(groupingPathStr, actualPath); + updatePath(groupingPathStr); + } + + @Override + public void exitUses_stmt(YangParser.Uses_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) { + super.enterLeaf_list_stmt(ctx); + + final String leafListName = stringFromNode(ctx); + QName leafListQName = new QName(namespace, revision, yangModelPrefix, + leafListName); + LeafListSchemaNodeBuilder leafListBuilder = moduleBuilder + .addLeafListNode(leafListQName, actualPath); + updatePath(leafListName); + + parseSchemaNodeArgs(ctx, leafListBuilder); + + for (int i = 0; i < ctx.getChildCount(); ++i) { + final ParseTree childNode = ctx.getChild(i); + if (childNode instanceof Config_stmtContext) { + leafListBuilder.setConfiguration(isLeafReadOnly(childNode)); + } else if (childNode instanceof Ordered_by_stmtContext) { + final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode; + final boolean userOrdered = parseUserOrdered(orderedBy); + leafListBuilder.setUserOrdered(userOrdered); + } + } + } + + @Override + public void exitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterList_stmt(List_stmtContext ctx) { + super.enterList_stmt(ctx); + + final String containerName = stringFromNode(ctx); + QName containerQName = new QName(namespace, revision, yangModelPrefix, + containerName); + ListSchemaNodeBuilder listBuilder = moduleBuilder.addListNode( + containerQName, actualPath); + updatePath(containerName); + + listBuilder.setPath(getActualSchemaPath(actualPath, namespace, + revision, yangModelPrefix)); + parseSchemaNodeArgs(ctx, listBuilder); + + String keyDefinition = ""; + for (int i = 0; i < ctx.getChildCount(); ++i) { + ParseTree childNode = ctx.getChild(i); + + if (childNode instanceof Ordered_by_stmtContext) { + final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode; + final boolean userOrdered = parseUserOrdered(orderedBy); + listBuilder.setUserOrdered(userOrdered); + } else if (childNode instanceof Key_stmtContext) { + List key = createListKey(keyDefinition, namespace, + revision, keyDefinition); + listBuilder.setKeyDefinition(key); + } + } + } + + @Override + public void exitList_stmt(List_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterNotification_stmt(YangParser.Notification_stmtContext ctx) { + final String notificationName = stringFromNode(ctx); + QName notificationQName = new QName(namespace, revision, + yangModelPrefix, notificationName); + NotificationBuilder notificationBuilder = moduleBuilder + .addNotification(notificationQName, actualPath); + updatePath(notificationName); + + notificationBuilder.setPath(getActualSchemaPath(actualPath, namespace, + revision, yangModelPrefix)); + parseSchemaNodeArgs(ctx, notificationBuilder); + } + + @Override + public void exitNotification_stmt(YangParser.Notification_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterRpc_stmt(YangParser.Rpc_stmtContext ctx) { + final String rpcName = stringFromNode(ctx); + QName rpcQName = new QName(namespace, revision, yangModelPrefix, + rpcName); + RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(rpcQName, + actualPath); + updatePath(rpcName); + + rpcBuilder.setPath(getActualSchemaPath(actualPath, namespace, revision, + yangModelPrefix)); + parseSchemaNodeArgs(ctx, rpcBuilder); + } + + @Override + public void exitRpc_stmt(YangParser.Rpc_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterInput_stmt(YangParser.Input_stmtContext ctx) { + updatePath("input"); + } + + @Override + public void exitInput_stmt(YangParser.Input_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterOutput_stmt(YangParser.Output_stmtContext ctx) { + updatePath("output"); + } + + @Override + public void exitOutput_stmt(YangParser.Output_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterFeature_stmt(YangParser.Feature_stmtContext ctx) { + final String featureName = stringFromNode(ctx); + QName featureQName = new QName(namespace, revision, yangModelPrefix, + featureName); + FeatureBuilder featureBuilder = moduleBuilder.addFeature(featureQName, + actualPath); + updatePath(featureName); + + featureBuilder.setPath(getActualSchemaPath(actualPath, namespace, + revision, yangModelPrefix)); + parseSchemaNodeArgs(ctx, featureBuilder); + } + + @Override + public void exitFeature_stmt(YangParser.Feature_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + @Override + public void enterDeviation_stmt(YangParser.Deviation_stmtContext ctx) { + final String targetPath = stringFromNode(ctx); + String reference = null; + String deviate = null; + DeviationBuilder builder = moduleBuilder.addDeviation(targetPath); + updatePath(targetPath); + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } else if (child instanceof Deviate_not_supported_stmtContext) { + deviate = stringFromNode(child); + } else if (child instanceof Deviate_add_stmtContext) { + deviate = stringFromNode(child); + } else if (child instanceof Deviate_replace_stmtContext) { + deviate = stringFromNode(child); + } else if (child instanceof Deviate_delete_stmtContext) { + deviate = stringFromNode(child); + } + } + builder.setReference(reference); + builder.setDeviate(deviate); + } + + @Override + public void exitDeviation_stmt(YangParser.Deviation_stmtContext ctx) { + final String actContainer = actualPath.pop(); + logger.debug("exiting " + actContainer); + } + + public ModuleBuilder getModuleBuilder() { + return moduleBuilder; + } + + private void updatePath(String containerName) { + actualPath.push(containerName); + } + + /** + * Parse ordered-by statement. + * + * @param childNode + * Ordered_by_stmtContext + * @return true, if ordered-by contains value 'user' or false otherwise + */ + private boolean parseUserOrdered(Ordered_by_stmtContext childNode) { + boolean result = false; + for (int j = 0; j < childNode.getChildCount(); j++) { + ParseTree orderArg = childNode.getChild(j); + if (orderArg instanceof Ordered_by_argContext) { + String orderStr = stringFromNode(orderArg); + if (orderStr.equals("system")) { + result = false; + } else if (orderStr.equals("user")) { + result = true; + } else { + logger.warn("Invalid 'ordered-by' statement."); + } + } + } + return result; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/util/YangModelBuilderHelper.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/util/YangModelBuilderHelper.java new file mode 100644 index 0000000000..7d9dcf19fb --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/model/parser/util/YangModelBuilderHelper.java @@ -0,0 +1,659 @@ +/* + * 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.controller.model.parser.util; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Stack; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bit_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificationContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Decimal64_specificationContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_specificationContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Fraction_digits_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Numerical_restrictionsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Pattern_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Position_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Range_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.String_restrictionsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext; +import org.opendaylight.controller.model.api.type.BitsTypeDefinition; +import org.opendaylight.controller.model.api.type.EnumTypeDefinition; +import org.opendaylight.controller.model.api.type.LengthConstraint; +import org.opendaylight.controller.model.api.type.PatternConstraint; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.model.api.type.BitsTypeDefinition.Bit; +import org.opendaylight.controller.model.parser.api.SchemaNodeBuilder; +import org.opendaylight.controller.model.util.BaseConstraints; +import org.opendaylight.controller.model.util.UnknownType; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class YangModelBuilderHelper { + + private static final Logger logger = LoggerFactory + .getLogger(YangModelBuilderHelper.class); + + /** + * Get 'description', 'reference' and 'status' statements and fill in + * builder. + * + * @param ctx + * context to parse + * @param builder + * builder to fill in with parsed statements + */ + public static void parseSchemaNodeArgs(ParseTree ctx, + SchemaNodeBuilder builder) { + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + String desc = stringFromNode(child); + builder.setDescription(desc); + } else if (child instanceof Reference_stmtContext) { + String ref = stringFromNode(child); + builder.setReference(ref); + } else if (child instanceof Status_stmtContext) { + Status status = getStatus((Status_stmtContext) child); + builder.setStatus(status); + } + } + } + + public static SchemaPath getActualSchemaPath(Stack actualPath, + URI namespace, Date revision, String prefix) { + final List path = new ArrayList(); + QName qname; + for (String pathElement : actualPath) { + qname = new QName(namespace, revision, prefix, pathElement); + path.add(qname); + } + return new SchemaPath(path, true); + } + + public static Status getStatus(Status_stmtContext ctx) { + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree statusArg = ctx.getChild(i); + if (statusArg instanceof Status_argContext) { + String statusArgStr = stringFromNode(statusArg); + if (statusArgStr.equals("current")) { + return Status.CURRENT; + } else if (statusArgStr.equals("deprecated")) { + return Status.DEPRECATED; + } else if (statusArgStr.equals("obsolete")) { + return Status.OBSOLOTE; + } else { + logger.warn("Invalid 'status' statement: " + statusArgStr); + } + } + } + return null; + } + + public static String stringFromNode(final ParseTree treeNode) { + final String result = ""; + for (int j = 0; j < treeNode.getChildCount(); ++j) { + if (treeNode.getChild(j) instanceof StringContext) { + final StringContext context = (StringContext) treeNode + .getChild(j); + + if (context != null) { + return context.getChild(0).getText().replace("\"", ""); + } + } + } + return result; + } + + public static SchemaPath parsePath(String augmentPath) { + boolean absolute = augmentPath.startsWith("/"); + String[] splittedPath = augmentPath.split("/"); + List path = new ArrayList(); + QName name; + for (String pathElement : splittedPath) { + if (pathElement.length() > 0) { + String[] splittedElement = pathElement.split(":"); + if (splittedElement.length == 1) { + name = new QName(null, null, null, splittedElement[0]); + } else { + name = new QName(null, null, splittedElement[0], + splittedElement[1]); + } + path.add(name); + } + } + return new SchemaPath(path, absolute); + } + + public static List createListKey(String keyDefinition, + URI namespace, Date revision, String prefix) { + List key = new ArrayList(); + String[] splittedKey = keyDefinition.split(" "); + + QName qname = null; + for (String keyElement : splittedKey) { + if (keyElement.length() != 0) { + qname = new QName(namespace, revision, prefix, keyElement); + key.add(qname); + } + } + return key; + } + + public static TypeDefinition parseUnknownType(QName typedefQName, + ParseTree ctx) { + UnknownType.Builder ut = new UnknownType.Builder(typedefQName); + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Type_body_stmtsContext) { + for (int j = 0; j < child.getChildCount(); j++) { + ParseTree typeBodyChild = child.getChild(j); + // NUMERICAL RESTRICTIONS + if (typeBodyChild instanceof Numerical_restrictionsContext) { + for (int k = 0; k < typeBodyChild.getChildCount(); k++) { + ParseTree numRestrictionsChild = typeBodyChild + .getChild(k); + if (numRestrictionsChild instanceof Range_stmtContext) { + List ranges = parseRangeConstraints((Range_stmtContext) numRestrictionsChild); + ut.rangeStatements(ranges); + } + } + // STRING RESTRICTIONS + } else if (typeBodyChild instanceof String_restrictionsContext) { + List patterns = new ArrayList(); + List lengths = new ArrayList(); + for (int k = 0; k < typeBodyChild.getChildCount(); k++) { + ParseTree stringRestrictionsChild = typeBodyChild + .getChild(k); + if (stringRestrictionsChild instanceof Pattern_stmtContext) { + patterns.add(parsePatternConstraint((Pattern_stmtContext) stringRestrictionsChild)); + } else if (stringRestrictionsChild instanceof Length_stmtContext) { + lengths = parseLengthConstraints((Length_stmtContext) stringRestrictionsChild); + } + } + ut.patterns(patterns); + ut.lengthStatements(lengths); + // DECIMAL64 + } else if (typeBodyChild instanceof Decimal64_specificationContext) { + for (int k = 0; k < typeBodyChild.getChildCount(); k++) { + ParseTree fdChild = typeBodyChild.getChild(k); + if (fdChild instanceof Fraction_digits_stmtContext) { + // TODO: implement fraction digits + // return + // Integer.valueOf(stringFromNode(fdChild)); + } + } + } + + } + } + } + return ut.build(); + } + + public static List getRangeConstraints( + Type_body_stmtsContext ctx) { + List rangeConstraints = new ArrayList(); + for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree numRestrChild = ctx.getChild(j); + if (numRestrChild instanceof Numerical_restrictionsContext) { + for (int k = 0; k < numRestrChild.getChildCount(); k++) { + ParseTree rangeChild = numRestrChild.getChild(k); + if (rangeChild instanceof Range_stmtContext) { + rangeConstraints + .addAll(parseRangeConstraints((Range_stmtContext) rangeChild)); + } + } + } + } + return rangeConstraints; + } + + private static List parseRangeConstraints( + Range_stmtContext ctx) { + List rangeConstraints = new ArrayList(); + String description = null; + String reference = null; + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } + } + + String rangeStr = stringFromNode(ctx); + String trimmed = rangeStr.replace(" ", ""); + String[] splittedRange = trimmed.split("\\|"); + for (String rangeDef : splittedRange) { + // TODO: this needs to be refactored, because valid range can be + // also defined as "1..max" + String[] splittedRangeDef = rangeDef.split("\\.\\."); + Long min = Long.valueOf(splittedRangeDef[0]); + Long max = Long.valueOf(splittedRangeDef[1]); + RangeConstraint range = BaseConstraints.rangeConstraint(min, max, + description, reference); + rangeConstraints.add(range); + } + + return rangeConstraints; + } + + public static Integer getFractionDigits(Type_body_stmtsContext ctx) { + for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree dec64specChild = ctx.getChild(j); + if (dec64specChild instanceof Decimal64_specificationContext) { + for (int k = 0; k < dec64specChild.getChildCount(); k++) { + ParseTree fdChild = dec64specChild.getChild(k); + if (fdChild instanceof Fraction_digits_stmtContext) { + return Integer.valueOf(stringFromNode(fdChild)); + } + } + } + } + return null; + } + + public static List getEnumConstants( + Type_body_stmtsContext ctx) { + List enumConstants = new ArrayList(); + + out: for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree enumSpecChild = ctx.getChild(j); + if (enumSpecChild instanceof Enum_specificationContext) { + for (int k = 0; k < enumSpecChild.getChildCount(); k++) { + ParseTree enumChild = enumSpecChild.getChild(k); + if (enumChild instanceof Enum_stmtContext) { + enumConstants.add(createEnumPair( + (Enum_stmtContext) enumChild, k)); + if (k == enumSpecChild.getChildCount() - 1) { + break out; + } + } + } + } + } + return enumConstants; + } + + private static EnumTypeDefinition.EnumPair createEnumPair( + Enum_stmtContext ctx, final int value) { + final String name = stringFromNode(ctx); + return new EnumTypeDefinition.EnumPair() { + + @Override + public QName getQName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public SchemaPath getPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getReference() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Status getStatus() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getExtensionSchemaNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getName() { + return name; + } + + @Override + public Integer getValue() { + return value; + } + + @Override + public String toString() { + return EnumTypeDefinition.EnumPair.class.getSimpleName() + + "[name=" + name + ", value=" + value + "]"; + } + }; + } + + public static List getLengthConstraints( + Type_body_stmtsContext ctx) { + List lengthConstraints = new ArrayList(); + for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree stringRestrChild = ctx.getChild(j); + if (stringRestrChild instanceof String_restrictionsContext) { + for (int k = 0; k < stringRestrChild.getChildCount(); k++) { + ParseTree lengthChild = stringRestrChild.getChild(k); + if (lengthChild instanceof Length_stmtContext) { + lengthConstraints + .addAll(parseLengthConstraints((Length_stmtContext) lengthChild)); + } + } + } + } + return lengthConstraints; + } + + private static List parseLengthConstraints( + Length_stmtContext ctx) { + List lengthConstraints = new ArrayList(); + String description = null; + String reference = null; + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } + } + + String lengthStr = stringFromNode(ctx); + String trimmed = lengthStr.replace(" ", ""); + String[] splittedRange = trimmed.split("\\|"); + for (String rangeDef : splittedRange) { + // TODO: this needs to be refactored, because valid length can be + // also defined as "1" + String[] splittedRangeDef = rangeDef.split("\\.\\."); + Long min = Long.valueOf(splittedRangeDef[0]); + Long max = Long.valueOf(splittedRangeDef[1]); + LengthConstraint range = BaseConstraints.lengthConstraint(min, max, + description, reference); + lengthConstraints.add(range); + } + + return lengthConstraints; + } + + public static List getPatternConstraint( + Type_body_stmtsContext ctx) { + List patterns = new ArrayList(); + + out: for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree stringRestrChild = ctx.getChild(j); + if (stringRestrChild instanceof String_restrictionsContext) { + for (int k = 0; k < stringRestrChild.getChildCount(); k++) { + ParseTree lengthChild = stringRestrChild.getChild(k); + if (lengthChild instanceof Pattern_stmtContext) { + patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild)); + if (k == lengthChild.getChildCount() - 1) { + break out; + } + } + } + } + } + return patterns; + } + + /** + * Internal helper method. + * + * @param ctx + * pattern context + * @return PatternConstraint object + */ + private static PatternConstraint parsePatternConstraint( + Pattern_stmtContext ctx) { + String description = null; + String reference = null; + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } + } + String pattern = stringFromNode(ctx); + return BaseConstraints.patternConstraint(pattern, description, + reference); + } + + public static List getBits( + Type_body_stmtsContext ctx, Stack actualPath, + URI namespace, Date revision, String prefix) { + List bits = new ArrayList(); + for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree bitsSpecChild = ctx.getChild(j); + if (bitsSpecChild instanceof Bits_specificationContext) { + for (int k = 0; k < bitsSpecChild.getChildCount(); k++) { + ParseTree bitChild = bitsSpecChild.getChild(k); + if (bitChild instanceof Bit_stmtContext) { + bits.add(parseBit((Bit_stmtContext) bitChild, + actualPath, namespace, revision, prefix)); + } + } + } + } + return bits; + } + + private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx, + Stack actualPath, final URI namespace, final Date revision, + final String prefix) { + String name = stringFromNode(ctx); + final QName qname = new QName(namespace, revision, prefix, name); + Long position = null; + + String description = null; + String reference = null; + Status status = Status.CURRENT; + + Stack bitPath = new Stack(); + bitPath.addAll(actualPath); + bitPath.add(name); + + SchemaPath schemaPath = getActualSchemaPath(bitPath, namespace, + revision, prefix); + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Position_stmtContext) { + String positionStr = stringFromNode(child); + position = Long.valueOf(positionStr); + if (position < 0 || position > 4294967295L) { + throw new IllegalArgumentException( + "position value MUST be in the range 0 to 4294967295, but was: " + + position); + } + } else if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } else if (child instanceof Status_stmtContext) { + status = getStatus((Status_stmtContext) child); + } + } + + // TODO: extensionDefinitions + return createBit(qname, schemaPath, description, reference, status, + null, position); + } + + private static BitsTypeDefinition.Bit createBit(final QName qname, + final SchemaPath schemaPath, final String description, + final String reference, final Status status, + final List extensionDefinitions, + final Long position) { + return new BitsTypeDefinition.Bit() { + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return schemaPath; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getReference() { + return reference; + } + + @Override + public Status getStatus() { + return status; + } + + @Override + public List getExtensionSchemaNodes() { + return extensionDefinitions; + } + + @Override + public Long getPosition() { + return position; + } + + @Override + public String getName() { + return qname.getLocalName(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((qname == null) ? 0 : qname.hashCode()); + result = prime * result + + ((schemaPath == null) ? 0 : schemaPath.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + + ((status == null) ? 0 : status.hashCode()); + result = prime * result + + ((position == null) ? 0 : position.hashCode()); + result = prime + * result + + ((extensionDefinitions == null) ? 0 + : extensionDefinitions.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Bit other = (Bit) obj; + if (qname == null) { + if (other.getQName() != null) { + return false; + } + } else if (!qname.equals(other.getQName())) { + return false; + } + if (schemaPath == null) { + if (other.getPath() != null) { + return false; + } + } else if (!schemaPath.equals(other.getPath())) { + return false; + } + if (description == null) { + if (other.getDescription() != null) { + return false; + } + } else if (!description.equals(other.getDescription())) { + return false; + } + if (reference == null) { + if (other.getReference() != null) { + return false; + } + } else if (!reference.equals(other.getReference())) { + return false; + } + if (status == null) { + if (other.getStatus() != null) { + return false; + } + } else if (!status.equals(other.getStatus())) { + return false; + } + if (extensionDefinitions == null) { + if (other.getExtensionSchemaNodes() != null) { + return false; + } + } else if (!extensionDefinitions.equals(other + .getExtensionSchemaNodes())) { + return false; + } + if (position == null) { + if (other.getPosition() != null) { + return false; + } + } else if (!position.equals(other.getPosition())) { + return false; + } + return true; + } + + @Override + public String toString() { + return Bit.class.getSimpleName() + "[name=" + + qname.getLocalName() + ", position=" + position + "]"; + } + }; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/ContainerSchemaNodeBuilderTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/ContainerSchemaNodeBuilderTest.java new file mode 100644 index 0000000000..55e1197716 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/ContainerSchemaNodeBuilderTest.java @@ -0,0 +1,118 @@ +/* + * 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.controller.model.parser.builder; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.model.parser.builder.ContainerSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.builder.MustDefinitionBuilder; +import org.opendaylight.controller.model.parser.builder.TypedefBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.ConstraintDefinition; +import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.MustDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +public class ContainerSchemaNodeBuilderTest { + + private ContainerSchemaNodeBuilder tested; + + private final String NAME = "test-container"; + + private final URI namespace = URI.create("test:container.name"); + private final Date revision = new Date(); + private final String prefix = "x"; + + private SchemaPath schemaPath; + private final String description = "description of container"; + private final String reference = "reference"; + + private QName typedefQName; + private TypedefBuilder typeBuilder; + @Mock private AugmentationSchema augment; + @Mock private ConstraintDefinition constraint; + @Mock private UsesNodeBuilder usesBuilder; + @Mock private UsesNode uses; + @Mock private MustDefinitionBuilder mustBuilder; + @Mock private MustDefinition must; + @Mock private GroupingBuilder groupingBuilder; + @Mock private GroupingDefinition grouping; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + when(usesBuilder.build()).thenReturn(uses); + when(mustBuilder.build()).thenReturn(must); + when(groupingBuilder.build()).thenReturn(grouping); + + schemaPath = TestUtils.createSchemaPath(true, namespace, "main", "interface"); + typedefQName = new QName(namespace, "test-type"); + typeBuilder = new TypedefBuilder(typedefQName); + + QName qname = new QName(namespace, revision, prefix, NAME); + tested = new ContainerSchemaNodeBuilder(qname); + } + + @Test + public void test() { + tested.addTypedef(typeBuilder); + tested.setPath(schemaPath); + tested.setDescription(description); + tested.setReference(reference); + tested.setStatus(Status.OBSOLOTE); + tested.setConfiguration(false); + tested.setConstraints(constraint); + tested.addUsesNode(usesBuilder); + tested.addAugmentation(augment); + tested.setMustDefinitionBuilder(mustBuilder); + tested.setPresenceContainer(true); + + ContainerSchemaNode result = tested.build(); + + Set> expectedTypedefs = result.getTypeDefinitions(); + assertEquals(1, expectedTypedefs.size()); + assertEquals(typedefQName, expectedTypedefs.iterator().next().getQName()); + + Set expectedAugments = new HashSet(); + expectedAugments.add(augment); + assertEquals(expectedAugments, result.getAvailableAugmentations()); + + assertEquals(schemaPath, result.getPath()); + assertEquals(description, result.getDescription()); + assertEquals(reference, result.getReference()); + assertEquals(Status.OBSOLOTE, result.getStatus()); + assertFalse(result.isConfiguration()); + assertEquals(constraint, result.getConstraints()); + + Set expectedUses = new HashSet(); + expectedUses.add(uses); + assertEquals(expectedUses, result.getUses()); + + assertTrue(result.isPresenceContainer()); + assertEquals(must, result.getMustDefinition()); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/LeafListSchemaNodeBuilderTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/LeafListSchemaNodeBuilderTest.java new file mode 100644 index 0000000000..9df458a233 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/LeafListSchemaNodeBuilderTest.java @@ -0,0 +1,99 @@ +/* + * 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.controller.model.parser.builder; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.util.Date; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.model.parser.builder.LeafSchemaNodeBuilder; +import org.opendaylight.controller.model.parser.builder.MustDefinitionBuilder; +import org.opendaylight.controller.model.parser.builder.TypedefBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ConstraintDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.LeafSchemaNode; +import org.opendaylight.controller.yang.model.api.MustDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +public class LeafListSchemaNodeBuilderTest { + + private LeafSchemaNodeBuilder tested; + + private final String NAME = "test-leaf"; + + private final URI namespace = URI.create("test:leaf.name"); + private final Date revision = new Date(); + private final String prefix = "x"; + + private SchemaPath schemaPath; + private final String description = "description of container"; + private final String reference = "reference"; + + private QName typedefQName; + private TypeDefinition type; + @Mock private ConstraintDefinition constraint; + @Mock private UsesNodeBuilder usesBuilder; + @Mock private UsesNode uses; + @Mock private MustDefinitionBuilder mustBuilder; + @Mock private MustDefinition must; + @Mock private GroupingBuilder groupingBuilder; + @Mock private GroupingDefinition grouping; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + when(usesBuilder.build()).thenReturn(uses); + when(mustBuilder.build()).thenReturn(must); + when(groupingBuilder.build()).thenReturn(grouping); + + schemaPath = TestUtils.createSchemaPath(true, namespace, "main", "interface"); + typedefQName = new QName(namespace, "test-type"); + TypedefBuilder typeBuilder = new TypedefBuilder(typedefQName); + type = typeBuilder.build(); + + QName qname = new QName(namespace, revision, prefix, NAME); + tested = new LeafSchemaNodeBuilder(qname); + } + + @Test + public void test() { + tested.setType(type); + tested.setPath(schemaPath); + tested.setDescription(description); + tested.setReference(reference); + tested.setStatus(Status.OBSOLOTE); + tested.setConfiguration(false); + tested.setConstraints(constraint); + tested.setMustDefinitionBuilder(mustBuilder); + + LeafSchemaNode result = tested.build(); + + assertEquals(type, result.getType()); + assertEquals(schemaPath, result.getPath()); + assertEquals(description, result.getDescription()); + assertEquals(reference, result.getReference()); + assertEquals(Status.OBSOLOTE, result.getStatus()); + assertFalse(result.isConfiguration()); + assertEquals(constraint, result.getConstraints()); + assertEquals(must, result.getMustDefinition()); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/ListSchemaNodeBuilderTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/ListSchemaNodeBuilderTest.java new file mode 100644 index 0000000000..7085dae3da --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/ListSchemaNodeBuilderTest.java @@ -0,0 +1,121 @@ +/* + * 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.controller.model.parser.builder; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.model.parser.api.GroupingBuilder; +import org.opendaylight.controller.model.parser.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.ConstraintDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.ListSchemaNode; +import org.opendaylight.controller.yang.model.api.MustDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; + + +public class ListSchemaNodeBuilderTest { + + private ListSchemaNodeBuilder tested; + + private static final String NAME = "test-list"; + + private final URI namespace = URI.create("test:list.name"); + private final Date revision = new Date(); + private final String prefix = "x"; + + private SchemaPath schemaPath; + private final String description = "description of list"; + private final String reference = "reference"; + + private QName typedefQName; + private TypedefBuilder typeBuilder; + @Mock private AugmentationSchema augment; + @Mock private ConstraintDefinition constraint; + @Mock private UsesNodeBuilder usesBuilder; + @Mock private UsesNode uses; + @Mock private MustDefinitionBuilder mustBuilder; + @Mock private MustDefinition must; + @Mock private GroupingBuilder groupingBuilder; + @Mock private GroupingDefinition grouping; + private List keyDefinition; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + when(usesBuilder.build()).thenReturn(uses); + when(mustBuilder.build()).thenReturn(must); + when(groupingBuilder.build()).thenReturn(grouping); + + schemaPath = TestUtils.createSchemaPath(true, namespace, "main", NAME); + typedefQName = new QName(namespace, "test-type"); + typeBuilder = new TypedefBuilder(typedefQName); + + keyDefinition = new ArrayList(); + keyDefinition.add(new QName(namespace, "name")); + + QName qname = new QName(namespace, revision, prefix, NAME); + tested = new ListSchemaNodeBuilder(qname); + } + + @Test + public void test() { + tested.addTypedef(typeBuilder); + tested.setPath(schemaPath); + tested.setDescription(description); + tested.setReference(reference); + tested.setStatus(Status.OBSOLOTE); + tested.setConfiguration(false); + tested.setConstraints(constraint); + tested.addUsesNode(usesBuilder); + tested.addAugmentation(augment); + tested.setUserOrdered(true); + tested.setKeyDefinition(keyDefinition); + + ListSchemaNode result = tested.build(); + + Set> expectedTypedefs = result.getTypeDefinitions(); + assertEquals(1, expectedTypedefs.size()); + assertEquals(typedefQName, expectedTypedefs.iterator().next().getQName()); + + Set expectedAugments = new HashSet(); + expectedAugments.add(augment); + assertEquals(expectedAugments, result.getAvailableAugmentations()); + + assertEquals(schemaPath, result.getPath()); + assertEquals(description, result.getDescription()); + assertEquals(reference, result.getReference()); + assertEquals(Status.OBSOLOTE, result.getStatus()); + assertFalse(result.isConfiguration()); + assertEquals(constraint, result.getConstraints()); + + Set expectedUses = new HashSet(); + expectedUses.add(uses); + assertEquals(expectedUses, result.getUses()); + + assertTrue(result.isUserOrdered()); + assertEquals(keyDefinition, result.getKeyDefinition()); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/TestUtils.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/TestUtils.java new file mode 100644 index 0000000000..0c5bb48324 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/builder/TestUtils.java @@ -0,0 +1,33 @@ +/* + * 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.controller.model.parser.builder; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.SchemaPath; + + +public class TestUtils { + + private TestUtils () { + } + + public static SchemaPath createSchemaPath(boolean absolute, URI namespace, String... path) { + List names = new ArrayList(); + QName qname; + for(String pathPart : path) { + qname = new QName(namespace, pathPart); + names.add(qname); + } + return new SchemaPath(names, absolute); + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/impl/YangModelParserTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/impl/YangModelParserTest.java new file mode 100644 index 0000000000..4a90d8033b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/model/parser/impl/YangModelParserTest.java @@ -0,0 +1,97 @@ +/* + * 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.controller.model.parser.impl; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Set; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.junit.Test; +import org.opendaylight.controller.antlrv4.code.gen.YangLexer; +import org.opendaylight.controller.antlrv4.code.gen.YangParser; +import org.opendaylight.controller.sal.binding.model.api.GeneratedType; + +public class YangModelParserTest { + + @Test + public void testPackageNameConstruction() { + try { + final InputStream inStream = getClass().getResourceAsStream( + "/simple-list-demo.yang"); + if (inStream != null) { + ANTLRInputStream input = new ANTLRInputStream(inStream); + final YangLexer lexer = new YangLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final YangParser parser = new YangParser(tokens); + + final ParseTree tree = parser.yang(); + final ParseTreeWalker walker = new ParseTreeWalker(); + + // final YangModelParserImpl modelParser = new + // YangModelParserImpl(tree, new TypeProviderImpl()); + // walker.walk(modelParser, tree); + // final Set genTypes = + // modelParser.generatedTypes(); + + // getTypesTest(genTypes); + + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void getTypesTest(final Set genTypes) { + int typesCount = 0; + for (final GeneratedType type : genTypes) { + if (type.getName().equals("Topology")) { + assertEquals(4, type.getMethodDefinitions().size()); + ++typesCount; + } + if (type.getName().equals("NetworkNodes")) { + assertEquals(2, type.getMethodDefinitions().size()); + ++typesCount; + } + if (type.getName().equals("NetworkNode")) { + assertEquals(1, type.getMethodDefinitions().size()); + ++typesCount; + } + if (type.getName().equals("NodeAttributes")) { + assertEquals(2, type.getMethodDefinitions().size()); + ++typesCount; + } + if (type.getName().equals("NetworkLinks")) { + assertEquals(2, type.getMethodDefinitions().size()); + ++typesCount; + } + if (type.getName().equals("NetworkLink")) { + assertEquals(3, type.getMethodDefinitions().size()); + ++typesCount; + } + if (type.getName().equals("Source")) { + assertEquals(2, type.getMethodDefinitions().size()); + ++typesCount; + } + if (type.getName().equals("Destination")) { + assertEquals(2, type.getMethodDefinitions().size()); + ++typesCount; + } + if (type.getName().equals("LinkAttributes")) { + assertEquals(0, type.getMethodDefinitions().size()); + ++typesCount; + } + } + assertEquals(9, typesCount); + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang1.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang1.yang new file mode 100644 index 0000000000..16d60875b9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang1.yang @@ -0,0 +1,60 @@ +module types1 { + yang-version 1; + namespace "urn:simple.container.demo"; + prefix "t1"; + + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + + container interfaces { + list ifEntry { + key "ifIndex"; + + leaf ifIndex { + type uint32; + } + leaf ifDescr { + type string; + } + leaf ifType { + type uint8; + } + leaf ifMtu { + type int32; + } + } + } + + + + + +// leaf name { +// type my-string; +// } + +// typedef my-string { +// type string { +// length "0..4"; +// pattern "[0-9a-fA-F]*"; +// } +// } + + +// leaf completed { +// type types2:percent; +// } + +// leaf testleaf { +// type data:my-base-int32-type; +// } + +// leaf-list domain-search { +// type string; +// description "List of domain names to search"; +// } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang2.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang2.yang new file mode 100644 index 0000000000..8c73b51a49 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang2.yang @@ -0,0 +1,27 @@ +module types2 { + yang-version 1; + namespace "urn:simple.types.data.demo"; + prefix "t2"; + + import types1 { + prefix "if"; + } + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description "This is types-data test description"; + + revision "2013-02-27" { + reference " WILL BE DEFINED LATER"; + } + + + augment "/if:interfaces/if:ifEntry" { + when "if:ifType='ds0'"; + leaf ds0ChannelNumber { + type string; + } + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang3.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang3.yang new file mode 100644 index 0000000000..0d09259f3e --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/yang3.yang @@ -0,0 +1,35 @@ +module types3 { + yang-version 1; + namespace "urn:simple.types3.data.demo"; + prefix "scd"; + + organization "Cisco"; + + contact "WILL-BE-DEFINED-LATER"; + + description "This is types-data test description"; + + revision "2013-02-27" { + reference " WILL BE DEFINED LATER"; + } + + typedef my-decimal { + type decimal64 { + fraction-digits 2; + } + } + + typedef my-base-int32-type { + type int32 { + range "0..32"; + } + } + + typedef percent { + type uint8 { + range "0 .. 100"; + } + description "Percentage"; + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/.gitignore b/opendaylight/sal/yang-prototype/sal/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/.gitignore @@ -0,0 +1 @@ +/target diff --git a/opendaylight/sal/yang-prototype/sal/pom.xml b/opendaylight/sal/yang-prototype/sal/pom.xml new file mode 100644 index 0000000000..7cda2acbae --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/pom.xml @@ -0,0 +1,90 @@ + + 4.0.0 + org.opendaylight.controller + sal + 1.0-SNAPSHOT + pom + + + sal-core-api + sal-data-api + sal-binding-api + sal-schema-repository-api + sal-common + sal-core-spi + ../yang + sal-broker-impl + sal-core-demo + + + + + + junit + junit + 4.10 + test + true + + + org.slf4j + slf4j-api + 1.7.2 + + + org.slf4j + slf4j-simple + 1.7.2 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0 + true + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + maven + + + + + aggregate + + site + + + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 2.4.0 + + Max + Low + site + + + + org.codehaus.mojo + jdepend-maven-plugin + 2.0-beta-2 + + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/.gitignore b/opendaylight/sal/yang-prototype/sal/sal-binding-api/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/.gitignore @@ -0,0 +1 @@ +/target diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-binding-api/pom.xml new file mode 100644 index 0000000000..b339e30070 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-binding-api + + + + org.opendaylight.controller + yang-common + 1.0 + + + org.opendaylight.controller + yang-binding + 1.0 + + + org.opendaylight.controller + sal-common + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareBroker.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareBroker.java new file mode 100644 index 0000000000..4c1e6f7e1c --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareBroker.java @@ -0,0 +1,167 @@ +/* + * 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.controller.sal.binding.api; + +import org.opendaylight.controller.yang.binding.RpcService; + +/** + * Binding-aware core of the SAL layer responsible for wiring the SAL consumers. + * + * The responsibility of the broker is to maintain registration of SAL + * functionality {@link Consumer}s and {@link Provider}s, store provider and + * consumer specific context and functionality registration via + * {@link ConsumerSession} and provide access to infrastructure services, which + * removes direct dependencies between providers and consumers. + * + * The Binding-aware broker is also responsible for translation from Java + * classes modeling the functionality and data to binding-indpenedent form which + * is used in SAL Core. + * + * + *

Infrastructure services

Some examples of infrastructure services: + * + *
    + *
  • YANG Module service - see {@link ConsumerSession#getRpcService(Class)}, + * {@link ProviderSession} + *
  • Notification Service - see {@link NotificationService} and + * {@link NotificationProviderService} + *
  • Functionality and Data model + *
  • Data Store access and modification - see {@link DataBrokerService} and + * {@link DataProviderService} + *
+ * + * The services are exposed via session. + * + *

Session-based access

+ * + * The providers and consumers needs to register in order to use the + * binding-independent SAL layer and to expose functionality via SAL layer. + * + * For more information about session-based access see {@link ConsumerSession} + * and {@link ProviderSession} + * + * + + * + */ +public interface BindingAwareBroker { + /** + * Registers the {@link BindingAwareConsumer}, which will use the SAL layer. + * + *

+ * Note that consumer could register additional functionality at later point + * by using service and functionality specific APIs. + * + *

+ * The consumer is required to use returned session for all communication + * with broker or one of the broker services. The session is announced to + * the consumer by invoking + * {@link Consumer#onSessionInitiated(ConsumerSession)}. + * + * @param cons + * Consumer to be registered. + * @return a session specific to consumer registration + * @throws IllegalArgumentException + * If the consumer is null. + * @throws IllegalStateException + * If the consumer is already registered. + */ + ConsumerSession registerConsumer(BindingAwareConsumer consumer); + + /** + * Registers the {@link BindingAwareProvider}, which will use the SAL layer. + * + *

+ * During the registration, the broker obtains the initial functionality + * from consumer, using the + * {@link BindingAwareProvider#getImplementations()}, and register that + * functionality into system and concrete infrastructure services. + * + *

+ * Note that provider could register additional functionality at later point + * by using service and functionality specific APIs. + * + *

+ * The consumer is required to use returned session for all + * communication with broker or one of the broker services. The session is + * announced to the consumer by invoking + * {@link BindingAwareProvider#onSessionInitiated(ProviderSession)}. + * + * + * @param prov + * Provider to be registered. + * @return a session unique to the provider registration. + * @throws IllegalArgumentException + * If the provider is null. + * @throws IllegalStateException + * If the consumer is already registered. + */ + ProviderSession registerProvider(BindingAwareProvider provider); + + /** + * {@link BindingAwareConsumer} specific access to the SAL functionality. + * + *

+ * ConsumerSession is {@link BindingAwareConsumer}-specific access to the + * SAL functionality and infrastructure services. + * + *

+ * The session serves to store SAL context (e.g. registration of + * functionality) for the consumer and provides access to the SAL + * infrastructure services and other functionality provided by + * {@link Provider}s. + * + + * + */ + public interface ConsumerSession { + + /** + * Returns a session specific instance (implementation) of requested + * binding-aware infrastructural service + * + * @param service + * Broker service + * @return Session specific implementation of service + */ + T getSALService(Class service); + + /** + * Returns a session specific instance (implementation) of requested + * YANG module implentation / service provided by consumer. + * + * @param service + * Broker service + * @return Session specific implementation of service + */ + T getRpcService(Class module); + } + + /** + * {@link BindingAwareProvider} specific access to the SAL functionality. + * + *

+ * ProviderSession is {@link BindingAwareProvider}-specific access to the + * SAL functionality and infrastructure services, which also allows for + * exposing the provider's functionality to the other + * {@link BindingAwareConsumer}s. + * + *

+ * The session serves to store SAL context (e.g. registration of + * functionality) for the providers and exposes access to the SAL + * infrastructure services, dynamic functionality registration and any other + * functionality provided by other {@link BindingAwareConsumer}s. + * + */ + public interface ProviderSession extends ConsumerSession { + + void addImplementation(RpcService implementation); + + void removeImplementation(RpcService implementation); + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareConsumer.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareConsumer.java new file mode 100644 index 0000000000..e32f8bc9f9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareConsumer.java @@ -0,0 +1,40 @@ +/* + * 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.controller.sal.binding.api; + +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerSession; + +/** + * + * Defines the component of controller and supplies additional metadata. A + * component of the controller or application supplies a concrete implementation + * of this interface. + * + * A user-implemented component (application) which faciliates the SAL and SAL + * services to access infrastructure services or providers' functionality. + * + + * + */ +public interface BindingAwareConsumer { + + /** + * Callback signaling initialization of the consumer session to the SAL. + * + * The consumer MUST use the session for all communication with SAL or + * retrieving SAL infrastructure services. + * + * This method is invoked by + * {@link BindingAwareBroker#registerConsumer(BindingAwareConsumer)} + * + * @param session + * Unique session between consumer and SAL. + */ + void onSessionInitialized(ConsumerSession session); + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareProvider.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareProvider.java new file mode 100644 index 0000000000..565c3d2f01 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareProvider.java @@ -0,0 +1,68 @@ +/* + * 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.controller.sal.binding.api; + +import java.util.Collection; + +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerSession; +import org.opendaylight.controller.yang.binding.RpcService; + + +/** + * + * Defines the component of controller and supplies additional metadata. A + * component of the controller or application supplies a concrete implementation + * of this interface. + * + *

+ * A user-implemented component (application) which facilitates the SAL and SAL + * services to access infrastructure services and to provide functionality to + * {@link Consumer}s and other providers. + * + + * + */ +public interface BindingAwareProvider { + + void onSessionInitialized(ConsumerSession session); + + /** + * Returns a set of provided implementations of YANG modules and their rpcs. + * + * + * @return Set of provided implementation of YANG modules and their Rpcs + */ + Collection getImplementations(); + + /** + * Gets a set of implementations of provider functionality to be registered + * into system during the provider registration to the SAL. + * + *

+ * This method is invoked by {@link Broker#registerProvider(Provider)} to + * learn the initial provided functionality + * + * @return Set of provider's functionality. + */ + Collection getFunctionality(); + + /** + * Functionality provided by the {@link BindingAwareProvider} + * + *

+ * Marker interface used to mark the interfaces describing specific + * functionality which could be exposed by providers to other components. + * + + * + */ + public interface ProviderFunctionality { + + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareService.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareService.java new file mode 100644 index 0000000000..e4d86e7bfd --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/BindingAwareService.java @@ -0,0 +1,40 @@ +/* + * 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.controller.sal.binding.api; + +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerSession; + +/** + * + * Session-specific instance of the broker functionality. + * + *

+ * BindingAwareService is marker interface for infrastructure services provided + * by the SAL. These services are session-specific, each + * {@link BindingAwareConsumer} and {@link BindingAwareProvider} usually has own + * instance of the service with it's own context. + * + *

+ * The consumer's (or provider's) instance of specific service could be obtained + * by invoking {@link ConsumerSession#getSALService(Class)} method on session + * assigned to the consumer. + * + *

+ * {@link BindingAwareService} and {@link BindingAwareProvider} may seem + * similar, but provider provides YANG model-based functionality and + * {@link BindingAwareProvider} exposes the necessary supporting functionality + * to implement specific functionality of YANG and to reuse it in the + * development of {@link BindingAwareConsumer}s and {@link BindingAwareProvider} + * s. + * + + * + */ +public interface BindingAwareService { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataBrokerService.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataBrokerService.java new file mode 100644 index 0000000000..9195b6f5c5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataBrokerService.java @@ -0,0 +1,137 @@ +/* + * 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.controller.sal.binding.api; + +import java.util.concurrent.Future; + +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.yang.binding.DataRoot; +import org.opendaylight.controller.yang.common.RpcResult; + + +/** + * DataBrokerService provides unified access to the data stores available in the + * system. + * + * + * @see DataProviderService + + */ +public interface DataBrokerService extends BindingAwareService { + + /** + * Returns a data from specified Data Store. + * + * Returns all the data visible to the consumer from specified Data Store. + * + * @param + * Interface generated from YANG module representing root of data + * @param store + * Identifier of the store, from which will be data retrieved + * @return data visible to the consumer + */ + T getData(DataStoreIdentifier store, Class rootType); + + /** + * Returns a filtered subset of data from specified Data Store. + * + *

+ * The filter is modeled as an hierarchy of Java TOs starting with + * implementation of {@link DataRoot} representing data root. The semantics + * of the filter tree is the same as filter semantics defined in the NETCONF + * protocol for rpc operations get and get-config + * in Section 6 of RFC6241. + * + * + * @see http://tools.ietf.org/html/rfc6241#section-6 + * @param + * Interface generated from YANG module representing root of data + * @param store + * Identifier of the store, from which will be data retrieved + * @param filter + * Data tree filter similar to the NETCONF filter + * @return + */ + T getData(DataStoreIdentifier store, T filter); + + /** + * Returns a candidate data which are not yet commited. + * + * + * @param + * Interface generated from YANG module representing root of data + * @param store + * Identifier of the store, from which will be data retrieved + * @return + */ + T getCandidateData(DataStoreIdentifier store, + Class rootType); + + /** + * Returns a filtered subset of candidate data from specified Data Store. + * + *

+ * The filter is modeled as an hierarchy of {@link Node} starting with + * {@link CompositeNode} representing data root. The semantics of the filter + * tree is the same as filter semantics defined in the NETCONF protocol for + * rpc operations get and get-config in Section 6 + * of RFC6241. + * + * + * @see http://tools.ietf.org/html/rfc6241#section-6 + * @param + * Interface generated from YANG module representing root of data + * @param store + * Identifier of the store, from which will be data retrieved + * @param filter + * A filter data root + * @return + */ + T getCandidateData(DataStoreIdentifier store, T filter); + + /** + * + * @param + * Interface generated from YANG module representing root of data + * @param store + * Identifier of the store, in which will be the candidate data + * modified + * @param changeSet + * Modification of data tree. + * @return Result object containing the modified data tree if the operation + * was successful, otherwise list of the encountered errors. + */ + RpcResult editCandidateData(DataStoreIdentifier store, + DataRoot changeSet); + + /** + * Initiates a two-phase commit of candidate data. + * + *

+ * The {@link Consumer} could initiate a commit of candidate data + * + *

+ * The successful commit changes the state of the system and may affect + * several components. + * + *

+ * The effects of successful commit of data are described in the + * specifications and YANG models describing the {@link Provider} components + * of controller. It is assumed that {@link Consumer} has an understanding + * of this changes. + * + * + * @see DataCommitHandler for further information how two-phase commit is + * processed. + * @param store + * Identifier of the store, where commit should occur. + * @return Result of the commit, containing success information or list of + * encountered errors, if commit was not successful. + */ + Future> commit(DataStoreIdentifier store); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataCommitHandler.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataCommitHandler.java new file mode 100644 index 0000000000..f568524c80 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataCommitHandler.java @@ -0,0 +1,209 @@ +/* + * 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.controller.sal.binding.api; + +import java.util.Set; + +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality; +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.yang.common.RpcResult; + + +/** + * Two phase commit handler (cohort) of the two-phase commit protocol of data. + * + *

+ * The provider should expose the implementation of DataCommitHandler if it's + * functionality depends on any subset of data stored in data repositories, in + * order to participate in {@link DataBrokerService#commit(DataStoreIdentifier) + * operation. + * + *

+ * Operations of two-phase commit handlers should not change data in data store, + * this is responsibility of the coordinator (broker or some component of the + * broker). + * + * The commit handlers are responsible for changing the internal state of the + * provider to reflect the commited changes in data. + * + *

Two-phase commit

+ * + *

Commit Request Phase

+ * + *
    + *
  1. Consumer edits data by invocation of + * DataBrokerService.editCandidateData(DataStoreIdentifier, DataRoot) + *
  2. Consumer starts a commit by invoking + * DataBrokerService.commit(DataStoreIdentifier) + *
  3. Broker retrieves a list of all registered + * DataCommitHandlers + *
  4. For each DataCommitHandler + *
      + *
    1. Broker invokes a + * DataCommitHandler.requestCommit(DataStoreIdentifier) operation. + *
    2. DataCommitHandler returns a RpcResult with + * CommitTransaction + *
    3. If the result was successful, broker adds CommitTransaction + * to the list of opened transactions. If not, brokers stops a commit request + * phase and starts a rollback phase. + *
    + *
  5. Broker starts a commit finish phase + *
+ * + *

Commit Finish Phase

+ * + *
    + *
  1. For each CommitTransaction from Commit Request phase + *
      + *
    1. Broker broker invokes a + * CommitTransaction.finish() + *
    2. The provider finishes a commit (applies the change) and returns an + * RpcResult. + *
    + *
  2. + *
      + *
    • If all returned results means successful, the brokers end two-phase + * commit by returning a success commit result to the Consumer. + *
    • If error occured, the broker starts a commit rollback phase. + *
    + *
+ * + *

Commit Rollback Phase

+ *
  • For each CommitTransaction from Commit Request phase + *
      + *
    1. Broker + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * broker invokes a {@link CommitTransaction#finish()} + *
    2. The provider rollbacks a commit and returns an {@link RpcResult} of + * rollback.
    + *
  • Broker returns a error result to the consumer. + * + * + *

    Registration of functionality

    + * The registration could be done by : + *
      + *
    • returning an instance of implementation in the return value of + * {@link Provider#getProviderFunctionality()} + *
    • passing an instance of implementation and {@link DataStoreIdentifier} of + * rpc as arguments to the + * {@link DataProviderService#addCommitHandler(DataStoreIdentifier, DataCommitHandler)} + *
    + * + + * + */ +public interface DataCommitHandler extends ProviderFunctionality { + /** + * A set of Data Stores supported by implementation. + * + * The set of {@link DataStoreIdentifier}s which identifies target data + * stores which are supported by this commit handler. This set is used, when + * {@link Provider} is registered to the SAL, to register and expose the + * commit handler functionality to affected data stores. + * + * @return Set of Data Store identifiers + */ + Set getSupportedDataStores(); + + /** + * The provider (commit handler) starts a commit transaction. + * + *

    + * The commit handler (provider) prepares an commit scenario, rollback + * scenario and validates data. + * + *

    + * If the provider is aware that at this point the commit would not be + * successful, the transaction is not created, but list of errors which + * prevented the start of transaction are returned. + * + * @param store + * @return Transaction object representing this commit, errors otherwise. + */ + RpcResult requestCommit(DataStoreIdentifier store); + + public interface CommitTransaction { + /** + * + * @return Data store affected by the transaction + */ + DataStoreIdentifier getDataStore(); + + /** + * Returns the handler associated with this transaction. + * + * @return Handler + */ + DataCommitHandler getHandler(); + + /** + * + * Finishes a commit. + * + * The provider (commit handler) should apply all changes to its state + * which are a result of data change- + * + * @return + */ + RpcResult finish() throws IllegalStateException; + + /** + * Rollbacks a commit. + * + * @return + * @throws IllegalStateException + * If the method is invoked after {@link #finish()} + */ + RpcResult rollback() throws IllegalStateException; + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataProviderService.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataProviderService.java new file mode 100644 index 0000000000..e4e7be5c6c --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataProviderService.java @@ -0,0 +1,85 @@ +/* + * 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.controller.sal.binding.api; + +import org.opendaylight.controller.sal.common.DataStoreIdentifier; + +public interface DataProviderService extends DataBrokerService { + + /** + * Adds {@link DataValidator} for specified Data Store + * + * @param store + * Data Store + * @param validator + * Validator + */ + public void addValidator(DataStoreIdentifier store, DataValidator validator); + + /** + * Removes {@link DataValidator} from specified Data Store + * + * @param store + * @param validator + * Validator + */ + public void removeValidator(DataStoreIdentifier store, + DataValidator validator); + + /** + * Adds {@link DataCommitHandler} for specified data store + * + * @param store + * @param provider + */ + void addCommitHandler(DataStoreIdentifier store, DataCommitHandler provider); + + /** + * Removes {@link DataCommitHandler} from specified data store + * + * @param store + * @param provider + */ + void removeCommitHandler(DataStoreIdentifier store, + DataCommitHandler provider); + + /** + * Adds {@link DataRefresher} for specified data store + * + * @param store + * @param refresher + */ + void addRefresher(DataStoreIdentifier store, DataRefresher refresher); + + /** + * Removes {@link DataRefresher} from specified data store + * + * @param store + * @param refresher + */ + void removeRefresher(DataStoreIdentifier store, DataRefresher refresher); + + /** + * Trigger for refreshing of the data exposed by the {@link Provider} + * + + * + */ + public interface DataRefresher extends + BindingAwareProvider.ProviderFunctionality { + + /** + * Fired when some component explicitly requested the data refresh. + * + * The provider which exposed the {@link DataRefresher} should republish + * its provided data by editing the data in all affected data stores. + */ + void refreshData(); + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataRefresher.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataRefresher.java new file mode 100644 index 0000000000..56b2a9f4da --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataRefresher.java @@ -0,0 +1,15 @@ +/* + * 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.controller.sal.binding.api; + +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality; + +public interface DataRefresher extends ProviderFunctionality { + + void refreshData(); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataValidator.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataValidator.java new file mode 100644 index 0000000000..f2ad68869a --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/DataValidator.java @@ -0,0 +1,18 @@ +/* + * 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.controller.sal.binding.api; + +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality; +import org.opendaylight.controller.yang.binding.DataRoot; +import org.opendaylight.controller.yang.common.RpcResult; + + +public interface DataValidator extends ProviderFunctionality { + + RpcResult validate(DataRoot data); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java new file mode 100644 index 0000000000..c5fc405f51 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java @@ -0,0 +1,15 @@ +/* + * 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.controller.sal.binding.api; + +import org.opendaylight.controller.yang.binding.Notification; + +public interface NotificationProviderService extends NotificationService { + + void notify(Notification notification); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java new file mode 100644 index 0000000000..92e30a5236 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java @@ -0,0 +1,22 @@ +/* + * 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.controller.sal.binding.api; + +import org.opendaylight.controller.yang.binding.Notification; +import org.opendaylight.controller.yang.binding.NotificationListener; + +public interface NotificationService extends BindingAwareService { + + void addNotificationListener( + Class notificationType, + NotificationListener listener); + + void removeNotificationListener( + Class notificationType, + NotificationListener listener); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/package-info.java new file mode 100644 index 0000000000..552ac6a450 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/package-info.java @@ -0,0 +1,9 @@ +/* + * 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.controller.sal.binding.api; + diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml new file mode 100644 index 0000000000..131630dcc3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml @@ -0,0 +1,31 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-binding-broker-impl + + + + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + + + org.opendaylight.controller + sal-core-api + 1.0-SNAPSHOT + + + + org.slf4j + slf4j-api + 1.6.4 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/pom.xml new file mode 100644 index 0000000000..131c00dc2a --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-broker-impl + + + org.opendaylight.controller + sal-core-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-core-spi + 1.0-SNAPSHOT + + + org.slf4j + slf4j-api + 1.6.4 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/BrokerImpl.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/BrokerImpl.java new file mode 100644 index 0000000000..97879fb969 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/BrokerImpl.java @@ -0,0 +1,130 @@ + +/* + * 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.controller.sal.core.impl; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import org.opendaylight.controller.sal.core.api.Broker; +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Consumer; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.sal.core.spi.BrokerModule; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.common.RpcResult; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class BrokerImpl implements Broker { + private static Logger log = LoggerFactory.getLogger(BrokerImpl.class); + + private Set sessions = new HashSet(); + private Set providerSessions = new HashSet(); + // private ExecutorService executor; + private Set modules = new HashSet(); + + private Map, BrokerModule> serviceProviders = new HashMap, BrokerModule>(); + + @Override + public ConsumerSession registerConsumer(Consumer consumer) { + checkPredicates(consumer); + log.info("Registering consumer " + consumer); + + ConsumerSessionImpl session = newSessionFor(consumer); + consumer.onSessionInitiated(session); + + sessions.add(session); + + return session; + + } + + @Override + public ProviderSession registerProvider(Provider provider) { + checkPredicates(provider); + + ProviderSessionImpl session = newSessionFor(provider); + provider.onSessionInitiated(session); + + providerSessions.add(session); + return session; + } + + public T serviceFor(Class service, + ConsumerSessionImpl session) { + BrokerModule prov = serviceProviders.get(service); + if (prov == null) { + log.warn("Service " + service.toString() + " is not supported"); + return null; + } + return prov.getServiceForSession(service, session); + } + + public Future> invokeRpc(QName rpc, + CompositeNode input) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + private void checkPredicates(Provider prov) { + if (prov == null) + throw new IllegalArgumentException("Provider should not be null."); + for (ProviderSessionImpl session : providerSessions) { + if (prov.equals(session.getProvider())) + throw new IllegalStateException("Provider already registered"); + } + + } + + private void checkPredicates(Consumer cons) { + if (cons == null) + throw new IllegalArgumentException("Consumer should not be null."); + for (ConsumerSessionImpl session : sessions) { + if (cons.equals(session.getConsumer())) + throw new IllegalStateException("Consumer already registered"); + } + } + + private ConsumerSessionImpl newSessionFor(Consumer cons) { + return new ConsumerSessionImpl(this, cons); + } + + private ProviderSessionImpl newSessionFor(Provider provider) { + return new ProviderSessionImpl(this, provider); + } + + public void addModule(BrokerModule module) { + log.info("Registering broker module " + module); + if (modules.contains(module)) { + log.error("Module already registered"); + throw new IllegalArgumentException("Module already exists."); + } + + Set> provServices = module + .getProvidedServices(); + for (Class serviceType : provServices) { + log.info(" Registering session service implementation: " + + serviceType.getCanonicalName()); + serviceProviders.put(serviceType, module); + } + } + + public void consumerSessionClosed(ConsumerSessionImpl consumerSessionImpl) { + sessions.remove(consumerSessionImpl); + providerSessions.remove(consumerSessionImpl); + } + +} + diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/BrokerServiceImpl.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/BrokerServiceImpl.java new file mode 100644 index 0000000000..4f254430bb --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/BrokerServiceImpl.java @@ -0,0 +1,16 @@ + +/* + * 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.controller.sal.core.impl; + +import org.opendaylight.controller.sal.core.api.BrokerService; + +abstract public class BrokerServiceImpl implements BrokerService { + + ConsumerSessionImpl session; +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/ConsumerSessionImpl.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/ConsumerSessionImpl.java new file mode 100644 index 0000000000..608c24b7b5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/ConsumerSessionImpl.java @@ -0,0 +1,69 @@ +/* + * 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.controller.sal.core.impl; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Future; + +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Consumer; +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.common.RpcResult; +import org.opendaylight.controller.yang.data.api.CompositeNode; + + +public class ConsumerSessionImpl implements ConsumerSession { + + private final BrokerImpl broker; + private final Consumer consumer; + + private Map, BrokerService> instantiatedServices = new HashMap, BrokerService>(); + + public Consumer getConsumer() { + return consumer; + } + + public ConsumerSessionImpl(BrokerImpl broker, Consumer consumer) { + this.broker = broker; + this.consumer = consumer; + } + + @Override + public Future> rpc(QName rpc, CompositeNode input) { + return broker.invokeRpc(rpc, input); + } + + @Override + public T getService(Class service) { + BrokerService potential = instantiatedServices.get(service); + if (potential != null) { + @SuppressWarnings("unchecked") + T ret = (T) potential; + return ret; + } + T ret = this.broker.serviceFor(service, this); + if (ret != null) { + instantiatedServices.put(service, ret); + } + return ret; + } + + @Override + public void close() { + Collection toStop = instantiatedServices.values(); + for (BrokerService brokerService : toStop) { + brokerService.closeSession(); + } + broker.consumerSessionClosed(this); + } + +} + diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/ProviderSessionImpl.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/ProviderSessionImpl.java new file mode 100644 index 0000000000..e87b8bbbb1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/ProviderSessionImpl.java @@ -0,0 +1,48 @@ + +/* + * 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.controller.sal.core.impl; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.yang.common.QName; + + +public class ProviderSessionImpl extends ConsumerSessionImpl implements + ProviderSession { + + private Provider provider; + + public ProviderSessionImpl(BrokerImpl broker, Provider provider) { + super(broker, null); + this.provider = provider; + } + + @Override + public void addRpcImplementation(QName rpcType, + RpcImplementation implementation) throws IllegalArgumentException { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public void removeRpcImplementation(QName rpcType, + RpcImplementation implementation) throws IllegalArgumentException { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + public Provider getProvider() { + return this.provider; + } + +} + diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/RpcUtils.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/RpcUtils.java new file mode 100644 index 0000000000..6edb981219 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/RpcUtils.java @@ -0,0 +1,74 @@ +/* + * 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.controller.sal.core.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; + +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.common.RpcError; +import org.opendaylight.controller.yang.common.RpcResult; +import org.opendaylight.controller.yang.data.api.CompositeNode; + + +public class RpcUtils { + + Callable> callableFor( + final RpcImplementation implemenation, final QName rpc, + final CompositeNode input) { + + return new Callable>() { + + @Override + public RpcResult call() throws Exception { + return implemenation.invokeRpc(rpc, input); + } + }; + } + + public static RpcResult getRpcResult(boolean successful, T result, + List errors) { + RpcResult ret = new RpcResultTO(successful, result, errors); + return ret; + } + + private static class RpcResultTO implements RpcResult { + + private final Collection errors; + private final T result; + private final boolean successful; + + public RpcResultTO(boolean successful, T result, List errors) { + this.successful = successful; + this.result = result; + this.errors = Collections.unmodifiableList(new ArrayList( + errors)); + } + + @Override + public boolean isSuccessful() { + return successful; + } + + @Override + public T getResult() { + return result; + } + + @Override + public Collection getErrors() { + return errors; + } + + } +} + diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/Utils.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/Utils.java new file mode 100644 index 0000000000..810049f44e --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/Utils.java @@ -0,0 +1,40 @@ +/* + * 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.controller.sal.core.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.opendaylight.controller.yang.common.QName; + + +public class Utils { + + public static void addToMap(Map> map, QName key, T value) { + List list = map.get(key); + if (list == null) { + list = new ArrayList(); + map.put(key, list); + } + list.add(value); + } + + public static void removeFromMap(Map> map, QName key, + T value) { + List list = map.get(key); + if (list == null) { + return; + } + list.remove(value); + if (list.isEmpty()) { + map.remove(key); + } + } +} + diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/data/DataBrokerModule.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/data/DataBrokerModule.java new file mode 100644 index 0000000000..7b93e5f08f --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/data/DataBrokerModule.java @@ -0,0 +1,411 @@ +/* + * 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.controller.sal.core.impl.data; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Future; + +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality; +import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality; +import org.opendaylight.controller.sal.core.api.data.DataBrokerService; +import org.opendaylight.controller.sal.core.api.data.DataCommitHandler; +import org.opendaylight.controller.sal.core.api.data.DataProviderService; +import org.opendaylight.controller.sal.core.api.data.DataValidator; +import org.opendaylight.controller.sal.core.api.data.DataCommitHandler.CommitTransaction; +import org.opendaylight.controller.sal.core.api.data.DataProviderService.DataRefresher; +import org.opendaylight.controller.sal.core.impl.RpcUtils; +import org.opendaylight.controller.sal.core.spi.BrokerModule; +import org.opendaylight.controller.yang.common.RpcError; +import org.opendaylight.controller.yang.common.RpcResult; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.CompositeNodeModification; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class DataBrokerModule implements BrokerModule { + + private static final Logger log = LoggerFactory + .getLogger(DataBrokerModule.class); + + private Map storeContext; + + private SequentialCommitHandlerCoordinator coordinator = new SequentialCommitHandlerCoordinator(); + + @Override + public Set> getProvidedServices() { + // FIXME: Refactor + Set> ret = new HashSet>(); + ret.add(DataBrokerService.class); + ret.add(DataProviderService.class); + return ret; + } + + @Override + public Set> getSupportedProviderFunctionality() { + // FIXME Refactor + Set> ret = new HashSet>(); + ret.add(DataValidator.class); + ret.add(DataCommitHandler.class); + ret.add(DataRefresher.class); + return ret; + } + + @Override + public T getServiceForSession(Class service, + ConsumerSession session) { + if (DataProviderService.class.equals(service) + && session instanceof ProviderSession) { + @SuppressWarnings("unchecked") + T ret = (T) newDataProviderService(session); + return ret; + } else if (DataBrokerService.class.equals(service)) { + + @SuppressWarnings("unchecked") + T ret = (T) newDataConsumerService(session); + return ret; + } + + throw new IllegalArgumentException( + "The requested session-specific service is not provided by this module."); + } + + private DataProviderService newDataProviderService(ConsumerSession session) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + private DataBrokerService newDataConsumerService(ConsumerSession session) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public Set> getSupportedConsumerFunctionality() { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + private static class StoreContext { + private Set commitHandlers = new HashSet(); + private Set validators = new HashSet(); + private Set refreshers = new HashSet(); + } + + private class DataConsumerSession implements DataBrokerService { + + @Override + public CompositeNode getData(DataStoreIdentifier store) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public CompositeNode getData(DataStoreIdentifier store, + CompositeNode filter) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public CompositeNode getCandidateData(DataStoreIdentifier store) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public CompositeNode getCandidateData(DataStoreIdentifier store, + CompositeNode filter) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public RpcResult editCandidateData( + DataStoreIdentifier store, CompositeNodeModification changeSet) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public Future> commit(DataStoreIdentifier store) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public void closeSession() { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + } + + private StoreContext context(DataStoreIdentifier store) { + return storeContext.get(store); + } + + private class DataProviderSession extends DataConsumerSession implements + DataProviderService { + + private Set providerCommitHandlers = new HashSet(); + private Set providerValidators = new HashSet(); + private Set providerRefreshers = new HashSet(); + + @Override + public void addValidator(DataStoreIdentifier store, + DataValidator validator) { + if (validator == null) + throw new IllegalArgumentException( + "Validator should not be null"); + + providerValidators.add(validator); + context(store).validators.add(validator); + } + + @Override + public void removeValidator(DataStoreIdentifier store, + DataValidator validator) { + if (validator == null) + throw new IllegalArgumentException( + "Validator should not be null"); + + providerValidators.remove(validator); + context(store).validators.remove(validator); + } + + @Override + public void addCommitHandler(DataStoreIdentifier store, + DataCommitHandler provider) { + if (provider == null) + throw new IllegalArgumentException( + "CommitHandler should not be null"); + + providerCommitHandlers.add(provider); + context(store).commitHandlers.add(provider); + } + + @Override + public void removeCommitHandler(DataStoreIdentifier store, + DataCommitHandler provider) { + if (provider == null) + throw new IllegalArgumentException( + "CommitHandler should not be null"); + + providerCommitHandlers.remove(provider); + context(store).commitHandlers.remove(provider); + } + + @Override + public void addRefresher(DataStoreIdentifier store, + DataRefresher provider) { + if (provider == null) + throw new IllegalArgumentException( + "Refresher should not be null"); + + providerRefreshers.add(provider); + context(store).refreshers.add(provider); + } + + @Override + public void removeRefresher(DataStoreIdentifier store, + DataRefresher provider) { + if (provider == null) + throw new IllegalArgumentException( + "Refresher should not be null"); + + providerRefreshers.remove(provider); + context(store).refreshers.remove(provider); + } + + } + + private class SequentialCommitHandlerCoordinator implements + DataCommitHandler { + + @Override + public RpcResult requestCommit( + DataStoreIdentifier store) { + List errors = new ArrayList(); + Set transactions = new HashSet(); + boolean successful = true; + + for (DataCommitHandler commitHandler : context(store).commitHandlers) { + try { + RpcResult partialResult = commitHandler + .requestCommit(store); + successful = partialResult.isSuccessful() & successful; + if (partialResult.isSuccessful()) { + transactions.add(partialResult.getResult()); + } + + errors.addAll(partialResult.getErrors()); + } catch (Exception e) { + log.error("Uncaught exception prevented commit request." + + e.getMessage(), e); + successful = false; + // FIXME: Add RPC Error with exception. + } + if (successful == false) + break; + } + CommitTransaction transaction = new SequentialCommitTransaction( + store, transactions); + return RpcUtils.getRpcResult(successful, transaction, errors); + } + + @Override + public Set getSupportedDataStores() { + return Collections.emptySet(); + } + } + + private class SequentialCommitTransaction implements CommitTransaction { + + final Set transactions; + final DataStoreIdentifier store; + + public SequentialCommitTransaction(DataStoreIdentifier s, + Set t) { + transactions = t; + store = s; + } + + @Override + public RpcResult finish() { + List errors = new ArrayList(); + boolean successful = true; + + for (CommitTransaction commitHandler : transactions) { + try { + RpcResult partialResult = commitHandler.finish(); + successful = partialResult.isSuccessful() & successful; + errors.addAll(partialResult.getErrors()); + } catch (Exception e) { + log.error( + "Uncaught exception prevented finishing of commit." + + e.getMessage(), e); + successful = false; + // FIXME: Add RPC Error with exception. + } + if (successful == false) + break; + } + + return RpcUtils.getRpcResult(successful, null, errors); + } + + @Override + public RpcResult rollback() { + List errors = new ArrayList(); + boolean successful = true; + + for (CommitTransaction commitHandler : transactions) { + try { + RpcResult partialResult = commitHandler.rollback(); + successful = partialResult.isSuccessful() & successful; + errors.addAll(partialResult.getErrors()); + } catch (Exception e) { + log.error( + "Uncaught exception prevented rollback of commit." + + e.getMessage(), e); + successful = false; + // FIXME: Add RPC Error with exception. + } + if (successful == false) + break; + } + + return RpcUtils.getRpcResult(successful, null, errors); + } + + @Override + public DataStoreIdentifier getDataStore() { + return this.store; + } + + @Override + public DataCommitHandler getHandler() { + return coordinator; + } + } + + private class ValidationCoordinator implements DataValidator { + + private final DataStoreIdentifier store; + + ValidationCoordinator(DataStoreIdentifier store) { + this.store = store; + } + + @Override + public RpcResult validate(CompositeNode toValidate) { + List errors = new ArrayList(); + boolean successful = true; + + for (DataValidator validator : context(store).validators) { + try { + RpcResult partialResult = validator + .validate(toValidate); + successful = partialResult.isSuccessful() & successful; + errors.addAll(partialResult.getErrors()); + } catch (Exception e) { + log.error( + "Uncaught exception prevented validation." + + e.getMessage(), e); + successful = false; + // FIXME: Add RPC Error with exception. + } + if (successful == false) + break; + } + + return RpcUtils.getRpcResult(successful, null, errors); + } + + @Override + public Set getSupportedDataStores() { + return Collections.emptySet(); + } + + } + + private class DataRefreshCoordinator implements DataRefresher { + + private final DataStoreIdentifier store; + + DataRefreshCoordinator(DataStoreIdentifier store) { + this.store = store; + } + + @Override + public void refreshData() { + + for (DataRefresher refresher : context(store).refreshers) { + try { + refresher.refreshData(); + } catch (Exception e) { + log.error( + "Uncaught exception during refresh of data: " + + e.getMessage(), e); + } + + } + } + } +} + diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/data/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/data/package-info.java new file mode 100644 index 0000000000..34fa5e4658 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/data/package-info.java @@ -0,0 +1,10 @@ + +/* + * 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.controller.sal.core.impl.data; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/notify/NotificationModule.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/notify/NotificationModule.java new file mode 100644 index 0000000000..fd19e7e6bc --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/notify/NotificationModule.java @@ -0,0 +1,182 @@ +/* + * 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.controller.sal.core.impl.notify; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality; +import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.controller.sal.core.api.notify.NotificationProviderService; +import org.opendaylight.controller.sal.core.api.notify.NotificationService; +import org.opendaylight.controller.sal.core.impl.BrokerServiceImpl; +import org.opendaylight.controller.sal.core.impl.Utils; +import org.opendaylight.controller.sal.core.spi.BrokerModule; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +public class NotificationModule implements BrokerModule { + private static Logger log = LoggerFactory + .getLogger(NotificationModule.class); + + private Map> listeners = new HashMap>(); + + @Override + public Set> getProvidedServices() { + // FIXME Refactor + Set> ret = new HashSet>(); + ret.add(NotificationService.class); + ret.add(NotificationProviderService.class); + return ret; + } + + @Override + public Set> getSupportedConsumerFunctionality() { + // FIXME Refactor + Set> ret = new HashSet>(); + ret.add(NotificationListener.class); + return ret; + } + + @Override + public T getServiceForSession(Class service, + ConsumerSession session) { + if (NotificationProviderService.class.equals(service) + && session instanceof ProviderSession) { + @SuppressWarnings("unchecked") + T ret = (T) newNotificationProviderService(session); + return ret; + } else if (NotificationService.class.equals(service)) { + + @SuppressWarnings("unchecked") + T ret = (T) newNotificationConsumerService(session); + return ret; + } + + throw new IllegalArgumentException( + "The requested session-specific service is not provided by this module."); + } + + private void sendNotification(CompositeNode notification) { + QName type = notification.getNodeType(); + List toNotify = listeners.get(type); + log.info("Publishing notification " + type); + + if (toNotify == null) { + // No listeners were registered - returns. + return; + } + + for (NotificationListener listener : toNotify) { + try { + // FIXME: ensure that notification is immutable + listener.onNotification(notification); + } catch (Exception e) { + log.error("Uncaught exception in NotificationListener", e); + } + } + + } + + private NotificationService newNotificationConsumerService( + ConsumerSession session) { + return new NotificationConsumerSessionImpl(); + } + + private NotificationProviderService newNotificationProviderService( + ConsumerSession session) { + return new NotificationProviderSessionImpl(); + } + + private class NotificationConsumerSessionImpl extends BrokerServiceImpl + implements NotificationService { + + Map> consumerListeners = new HashMap>(); + private boolean closed = false; + + @Override + public void addNotificationListener(QName notification, + NotificationListener listener) { + checkSessionState(); + if (notification == null) { + throw new IllegalArgumentException( + "Notification type must not be null."); + } + if (listener == null) { + throw new IllegalArgumentException("Listener must not be null."); + } + + Utils.addToMap(consumerListeners, notification, listener); + Utils.addToMap(listeners, notification, listener); + log.info("Registered listener for notification: " + notification); + } + + @Override + public void removeNotificationListener(QName notification, + NotificationListener listener) { + checkSessionState(); + if (notification == null) { + throw new IllegalArgumentException( + "Notification type must not be null."); + } + if (listener == null) { + throw new IllegalArgumentException("Listener must not be null."); + } + Utils.removeFromMap(consumerListeners, notification, listener); + Utils.removeFromMap(listeners, notification, listener); + } + + @Override + public void closeSession() { + closed = true; + Set>> toRemove = consumerListeners + .entrySet(); + for (Entry> entry : toRemove) { + listeners.get(entry.getKey()).removeAll(entry.getValue()); + } + } + + protected void checkSessionState() { + if (closed) + throw new IllegalStateException("Session is closed"); + } + } + + private class NotificationProviderSessionImpl extends + NotificationConsumerSessionImpl implements + NotificationProviderService { + + @Override + public void sendNotification(CompositeNode notification) { + checkSessionState(); + if (notification == null) + throw new IllegalArgumentException( + "Notification must not be null."); + NotificationModule.this.sendNotification(notification); + } + } + + @Override + public Set> getSupportedProviderFunctionality() { + return Collections.emptySet(); + } +} + diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/notify/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/notify/package-info.java new file mode 100644 index 0000000000..c068196bde --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/notify/package-info.java @@ -0,0 +1,9 @@ +/* + * 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.controller.sal.core.impl.notify; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/package-info.java new file mode 100644 index 0000000000..e29549df2d --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.core.impl; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/rpc/RpcModule.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/rpc/RpcModule.java new file mode 100644 index 0000000000..58ceb5f51b --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/rpc/RpcModule.java @@ -0,0 +1,5 @@ +package org.opendaylight.controller.sal.core.impl.rpc; + +public interface RpcModule { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/rpc/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/rpc/package-info.java new file mode 100644 index 0000000000..41e9bcbd27 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-broker-impl/src/main/java/org/opendaylight/controller/sal/core/impl/rpc/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.core.impl.rpc; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-common/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-common/pom.xml new file mode 100644 index 0000000000..a144b542da --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-common/pom.xml @@ -0,0 +1,14 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-common + + + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/DataStoreIdentifier.java b/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/DataStoreIdentifier.java new file mode 100644 index 0000000000..194045ebff --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/DataStoreIdentifier.java @@ -0,0 +1,21 @@ +/* + * 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.controller.sal.common; + +public interface DataStoreIdentifier { + + Object getIdentifier(); + + String getName(); + + @Override + public boolean equals(Object obj); + + @Override + public int hashCode(); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/GlobalDataStore.java b/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/GlobalDataStore.java new file mode 100644 index 0000000000..1c302383e1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/GlobalDataStore.java @@ -0,0 +1,29 @@ +/* + * 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.controller.sal.common; + +public enum GlobalDataStore implements DataStoreIdentifier { + RuntimeInfo("Runtime Info"), Configuration("Configuration"); + + private final String name; + + GlobalDataStore(String name) { + this.name = name; + } + + @Override + public Object getIdentifier() { + return this; + } + + @Override + public String getName() { + return this.name; + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/package-info.java new file mode 100644 index 0000000000..e28fa9442f --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-common/src/main/java/org/opendaylight/controller/sal/common/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.common; diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/.gitignore b/opendaylight/sal/yang-prototype/sal/sal-core-api/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/.gitignore @@ -0,0 +1 @@ +/target diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-core-api/pom.xml new file mode 100644 index 0000000000..abdd3ad656 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-core-api + + + + org.opendaylight.controller + sal-common + 1.0-SNAPSHOT + + + org.opendaylight.controller + yang-data-api + 1.0 + + + org.opendaylight.controller + yang-model-api + 1.0 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Broker.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Broker.java new file mode 100644 index 0000000000..19c3e17779 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Broker.java @@ -0,0 +1,233 @@ +/* + * 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.controller.sal.core.api; + +import java.util.concurrent.Future; + +import org.opendaylight.controller.sal.core.api.data.DataBrokerService; +import org.opendaylight.controller.sal.core.api.data.DataProviderService; +import org.opendaylight.controller.sal.core.api.notify.NotificationProviderService; +import org.opendaylight.controller.sal.core.api.notify.NotificationService; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.common.RpcResult; +import org.opendaylight.controller.yang.data.api.CompositeNode; + + +/** + * Core component of the SAL layer responsible for wiring the SAL consumers. + * + * The responsibility of the broker is to maintain registration of SAL + * functionality {@link Consumer}s and {@link Provider}s, store provider and + * consumer specific context and functionality registration via + * {@link ConsumerSession} and provide access to infrastructure services, which + * removes direct dependencies between providers and consumers. + * + * + *

    Infrastructure services

    Some examples of infrastructure services: + * + *
      + *
    • RPC Invocation - see {@link ConsumerSession#rpc(QName, CompositeNode)}, + * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)} and + * {@link RpcImplementation} + *
    • Notification Service - see {@link NotificationService} and + * {@link NotificationProviderService} + *
    • Functionality and Data model + *
    • Data Store access and modification - see {@link DataBrokerService} and + * {@link DataProviderService} + *
    + * + * The services are exposed via session. + * + *

    Session-based access

    + * + * The providers and consumers needs to register in order to use the + * binding-independent SAL layer and to expose functionality via SAL layer. + * + * For more information about session-based access see {@link ConsumerSession} + * and {@link ProviderSession} + * + * + * + */ +public interface Broker { + + /** + * Registers the {@link Consumer}, which will use the SAL layer. + * + *

    + * During the registration, the broker obtains the initial functionality + * from consumer, using the {@link Consumer#getConsumerFunctionality()}, and + * register that functionality into system and concrete infrastructure + * services. + * + *

    + * Note that consumer could register additional functionality at later point + * by using service and functionality specific APIs. + * + *

    + * The consumer is required to use returned session for all communication + * with broker or one of the broker services. The session is announced to + * the consumer by invoking + * {@link Consumer#onSessionInitiated(ConsumerSession)}. + * + * @param cons + * Consumer to be registered. + * @return a session specific to consumer registration + * @throws IllegalArgumentException + * If the consumer is null. + * @throws IllegalStateException + * If the consumer is already registered. + */ + ConsumerSession registerConsumer(Consumer cons); + + /** + * Registers the {@link Provider}, which will use the SAL layer. + * + *

    + * During the registration, the broker obtains the initial functionality + * from consumer, using the {@link Provider#getProviderFunctionality()}, and + * register that functionality into system and concrete infrastructure + * services. + * + *

    + * Note that consumer could register additional functionality at later point + * by using service and functionality specific APIs (e.g. + * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)} + * + *

    + * The consumer is required to use returned session for all + * communication with broker or one of the broker services. The session is + * announced to the consumer by invoking + * {@link Provider#onSessionInitiated(ProviderSession)}. + * + * + * @param prov + * Provider to be registered. + * @return a session unique to the provider registration. + * @throws IllegalArgumentException + * If the provider is null. + * @throws IllegalStateException + * If the consumer is already registered. + */ + ProviderSession registerProvider(Provider prov); + + /** + * {@link Consumer} specific access to the SAL functionality. + * + *

    + * ConsumerSession is {@link Consumer}-specific access to the SAL + * functionality and infrastructure services. + * + *

    + * The session serves to store SAL context (e.g. registration of + * functionality) for the consumer and provides access to the SAL + * infrastructure services and other functionality provided by + * {@link Provider}s. + * + + * + */ + public interface ConsumerSession { + + /** + * Sends an RPC to other components registered to the broker. + * + * @see RpcImplementation + * @param rpc + * Name of RPC + * @param input + * Input data to the RPC + * @return Result of the RPC call + */ + Future> rpc(QName rpc, CompositeNode input); + + /** + * Returns a session specific instance (implementation) of requested + * service + * + * @param service + * Broker service + * @return Session specific implementation of service + */ + T getService(Class service); + + /** + * Closes a session between consumer and broker. + * + *

    + * The close operation unregisters a consumer and remove all registered + * functionality of the consumer from the system. + * + */ + void close(); + } + + /** + * {@link Provider} specific access to the SAL functionality. + * + *

    + * ProviderSession is {@link Provider}-specific access to the SAL + * functionality and infrastructure services, which also allows for exposing + * the provider's functionality to the other {@link Consumer}s. + * + *

    + * The session serves to store SAL context (e.g. registration of + * functionality) for the providers and exposes access to the SAL + * infrastructure services, dynamic functionality registration and any other + * functionality provided by other {@link Provider}s. + * + */ + public interface ProviderSession extends ConsumerSession { + /** + * Registers an implementation of the rpc. + * + *

    + * The registered rpc functionality will be available to all other + * consumers and providers registered to the broker, which are aware of + * the {@link QName} assigned to the rpc. + * + *

    + * There is no assumption that rpc type is in the set returned by + * invoking {@link RpcImplementation#getSupportedRpcs()}. This allows + * for dynamic rpc implementations. + * + * @param rpcType + * Name of Rpc + * @param implementation + * Provider's Implementation of the RPC functionality + * @throws IllegalArgumentException + * If the name of RPC is invalid + */ + void addRpcImplementation(QName rpcType, + RpcImplementation implementation) + throws IllegalArgumentException; + + /** + * Unregisters an Rpc implementation + * + * @param rpcType + * Name of Rpc + * @param implementation + * Registered Implementation of the Rpc functionality + * @throws IllegalArgumentException + */ + void removeRpcImplementation(QName rpcType, + RpcImplementation implementation) + throws IllegalArgumentException; + + /** + * Closes a session between provider and SAL. + * + *

    + * The close operation unregisters a provider and remove all registered + * functionality of the provider from the system. + */ + @Override + public void close(); + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/BrokerService.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/BrokerService.java new file mode 100644 index 0000000000..b854188f61 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/BrokerService.java @@ -0,0 +1,39 @@ +/* + * 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.controller.sal.core.api; + +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; + +/** + * + * Session-specific instance of the broker functionality. + * + *

    + * BrokerService is marker interface for infrastructure services provided by the + * SAL. These services are session-specific, each {@link Provider} and + * {@link Consumer} usually has own instance of the service with it's own + * context. + * + *

    + * The consumer's (or provider's) instance of specific service could be obtained + * by invoking {@link ConsumerSession#getService(Class)} method on session + * assigned to the consumer. + * + *

    + * {@link BrokerService} and {@link Provider} may seem similar, but provider + * provides YANG model-based functionality and {@link BrokerService} exposes the + * necessary supporting functionality to implement specific functionality of + * YANG and to reuse it in the development of {@link Consumer}s and + * {@link Provider}s. + * + * + */ +public interface BrokerService { + + void closeSession(); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Consumer.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Consumer.java new file mode 100644 index 0000000000..1b223f9e66 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Consumer.java @@ -0,0 +1,59 @@ +/* + * 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.controller.sal.core.api; + +import java.util.Collection; + +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; + +/** + * + * Defines the component of controller and supplies additional metadata. A + * component of the controller or application supplies a concrete implementation + * of this interface. + * + * A user-implemented component (application) which faciliates the SAL and SAL + * services to access infrastructure services or providers' functionality. + * + * + */ +public interface Consumer { + + /** + * Callback signaling initialization of the consumer session to the SAL. + * + * The consumer MUST use the session for all communication with SAL or + * retrieving SAL infrastructure services. + * + * This method is invoked by {@link Broker#registerConsumer(Consumer)} + * + * @param session + * Unique session between consumer and SAL. + */ + public void onSessionInitiated(ConsumerSession session); + + /** + * Get a set of implementations of consumer functionality to be registered + * into system during the consumer registration to the SAL. + * + * This method is invoked by {@link Broker#registerConsumer(Consumer)}. + * + * @return Set of consumer functionality. + */ + public Collection getConsumerFunctionality(); + + /** + * The marker interface for the interfaces describing the consumer + * functionality contracts. + * + * + */ + public interface ConsumerFunctionality { + + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Provider.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Provider.java new file mode 100644 index 0000000000..dff636fd4b --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/Provider.java @@ -0,0 +1,69 @@ +/* + * 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.controller.sal.core.api; + +import java.util.Collection; + +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; + +/** + * + * Defines the component of controller and supplies additional metadata. A + * component of the controller or application supplies a concrete implementation + * of this interface. + * + *

    + * A user-implemented component (application) which faciliates the SAL and SAL + * services to access infrastructure services and to provide functionality to + * {@link Consumer}s and other providers. + * + * + */ +public interface Provider { + + /** + * Callback signaling initialization of the provider session to the SAL. + * + *

    + * The provider MUST use the session for all communication with SAL + * or retrieving SAL infrastructure services. + * + *

    + * This method is invoked by {@link Broker#registerConsumer(Consumer)} + * + * @param session + * Unique session between provider and SAL. + */ + public void onSessionInitiated(ProviderSession session); + + /** + * Gets a set of implementations of provider functionality to be registered + * into system during the provider registration to the SAL. + * + *

    + * This method is invoked by {@link Broker#registerProvider(Provider)} to + * learn the initial provided functionality + * + * @return Set of provider's functionality. + */ + public Collection getProviderFunctionality(); + + /** + * Functionality provided by the {@link Provider} + * + *

    + * Marker interface used to mark the interfaces describing specific + * functionality which could be exposed by providers to other components. + * + + * + */ + public interface ProviderFunctionality { + + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java new file mode 100644 index 0000000000..ef5aa703b9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java @@ -0,0 +1,81 @@ +/* + * 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.controller.sal.core.api; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.common.RpcResult; +import org.opendaylight.controller.yang.data.api.CompositeNode; + +/** + * {@link Provider}'s implementation of rpc. + * + * In order to expose the rpc to other components, the provider MUST register + * concrete implementation of this interface + * + * The registration could be done by : + *

      + *
    • returning an instance of implementation in the return value of + * {@link Provider#getProviderFunctionality()} + *
    • passing an instance of implementation and {@link QName} of rpc as + * arguments to the + * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)} + *
    + * + * The simplified process of the invocation of rpc is following: + * + *
      + *
    1. {@link Consumer} invokes + * {@link ConsumerSession#rpc(QName, CompositeNode)} + *
    2. {@link Broker} finds registered {@link RpcImplementation}s + *
    3. {@link Broker} invokes + * {@link RpcImplementation#invokeRpc(QName, CompositeNode)} + *
    4. {@link RpcImplementation} processes the data and returns a + * {@link RpcResult} + *
    5. {@link Broker} returns the {@link RpcResult} to {@link Consumer} + *
    + * + * + */ +public interface RpcImplementation extends Provider.ProviderFunctionality { + + /** + * A set of rpc types supported by implementation. + * + * The set of rpc {@link QName}s which are supported by this implementation. + * This set is used, when {@link Provider} is registered to the SAL, to + * register and expose the implementation of the returned rpcs. + * + * @return Set of QNames identifying supported RPCs + */ + Set getSupportedRpcs(); + + /** + * Invokes a implementation of specified rpc. + * + * + * @param rpc + * Rpc to be invoked + * @param input + * Input data for rpc. + * + * @throws IllegalArgumentException + *
      + *
    • If rpc is null. + *
    • If input is not null and + * false == rpc.equals(input.getNodeType) + *
    + * @return RpcResult containing the output of rpc if was executed + * successfully, the list of errors otherwise. + */ + RpcResult invokeRpc(QName rpc, CompositeNode input); + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataBrokerService.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataBrokerService.java new file mode 100644 index 0000000000..f5f393852e --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataBrokerService.java @@ -0,0 +1,132 @@ +/* + * 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.controller.sal.core.api.data; + +import java.util.concurrent.Future; + +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Consumer; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.yang.common.RpcResult; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.CompositeNodeModification; +import org.opendaylight.controller.yang.data.api.Node; + + +/** + * DataBrokerService provides unified access to the data stores available in the + * system. + * + * + * @see DataProviderService + * + */ +public interface DataBrokerService extends BrokerService { + + /** + * Returns a data from specified Data Store. + * + * Returns all the data visible to the consumer from specified Data Store. + * + * @param store + * Identifier of the store, from which will be data retrieved + * @return data visible to the consumer + */ + CompositeNode getData(DataStoreIdentifier store); + + /** + * Returns a filtered subset of data from specified Data Store. + * + *

    + * The filter is modeled as an hierarchy of {@link Node} starting with + * {@link CompositeNode} representing data root. The semantics of the filter + * tree is the same as filter semantics defined in the NETCONF protocol for + * rpc operations get and get-config in Section 6 + * of RFC6241. + * + * + * @see http://tools.ietf.org/html/rfc6241#section-6 + * @param store + * Identifier of the store, from which will be data retrieved + * @param filter + * Data tree filter similar to the NETCONF filter + * @return + */ + CompositeNode getData(DataStoreIdentifier store, CompositeNode filter); + + /** + * Returns a candidate data which are not yet commited. + * + * + * @param store + * Identifier of the store, from which will be data retrieved + * @return + */ + CompositeNode getCandidateData(DataStoreIdentifier store); + + /** + * Returns a filtered subset of candidate data from specified Data Store. + * + *

    + * The filter is modeled as an hierarchy of {@link Node} starting with + * {@link CompositeNode} representing data root. The semantics of the filter + * tree is the same as filter semantics defined in the NETCONF protocol for + * rpc operations get and get-config in Section 6 + * of RFC6241. + * + * + * @see http://tools.ietf.org/html/rfc6241#section-6 + * @param store + * Identifier of the store, from which will be data retrieved + * @param filter + * A CompositeNode filter + * @return + */ + CompositeNode getCandidateData(DataStoreIdentifier store, + CompositeNode filter); + + /** + * + * @param store + * Identifier of the store, in which will be the candidate data + * modified + * @param changeSet + * Modification of data tree. + * @return Result object containing the modified data tree if the operation + * was successful, otherwise list of the encountered errors. + */ + RpcResult editCandidateData(DataStoreIdentifier store, + CompositeNodeModification changeSet); + + /** + * Initiates a two-phase commit of candidate data. + * + *

    + * The {@link Consumer} could initiate a commit of candidate data + * + *

    + * The successful commit changes the state of the system and may affect + * several components. + * + *

    + * The effects of successful commit of data are described in the + * specifications and YANG models describing the {@link Provider} components + * of controller. It is assumed that {@link Consumer} has an understanding + * of this changes. + * + * + * @see DataCommitHandler for further information how two-phase commit is + * processed. + * @param store + * Identifier of the store, where commit should occur. + * @return Result of the commit, containing success information or list of + * encountered errors, if commit was not successful. + */ + Future> commit(DataStoreIdentifier store); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataCommitHandler.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataCommitHandler.java new file mode 100644 index 0000000000..f0cc02d3ce --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataCommitHandler.java @@ -0,0 +1,164 @@ +/* + * 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.controller.sal.core.api.data; + +import java.util.Set; + +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.yang.common.RpcResult; + + +/** + * Two phase commit handler (cohort) of the two-phase commit protocol of data. + * + *

    + * The provider should expose the implementation of DataCommitHandler if it's + * functionality depends on any subset of data stored in data repositories, in + * order to participate in {@link DataBrokerService#commit(DataStoreIdentifier) + * operation. + * + *

    + * Operations of two-phase commit handlers should not change data in data store, + * this is responsibility of the coordinator (broker or some component of the + * broker). + * + * The commit handlers are responsible for changing the internal state of the + * provider to reflect the commited changes in data. + * + *

    Two-phase commit

    + * + *

    Commit Request Phase

    + * + *
      + *
    1. Consumer edits data by invocation of + * DataBrokerService.editCandidateData(DataStoreIdentifier, CompositeNodeModification) + *
    2. Consumer starts a commit by invoking + * DataBrokerService.commit(DataStoreIdentifier) + *
    3. Broker retrieves a list of all registered + * DataCommitHandlers + *
    4. For each DataCommitHandler + *
        + *
      1. Broker invokes a + * DataCommitHandler.requestCommit(DataStoreIdentifier) operation. + *
      2. DataCommitHandler returns a RpcResult with + * CommitTransaction + *
      3. If the result was successful, broker adds CommitTransaction + * to the list of opened transactions. If not, brokers stops a commit request + * phase and starts a rollback phase. + *
      + *
    5. Broker starts a commit finish phase + *
    + * + *

    Commit Finish Phase

    + * + *
      + *
    1. For each CommitTransaction from Commit Request phase + *
        + *
      1. Broker broker invokes a + * CommitTransaction.finish() + *
      2. The provider finishes a commit (applies the change) and returns an + * RpcResult. + *
      + *
    2. + *
        + *
      • If all returned results means successful, the brokers end two-phase + * commit by returning a success commit result to the Consumer. + *
      • If error occured, the broker starts a commit rollback phase. + *
      + *
    + * + *

    Commit Rollback Phase

    + *
  • For each CommitTransaction from Commit Request phase + *
      + *
    1. Broker + * + * broker invokes a {@link CommitTransaction#finish()} + *
    2. The provider rollbacks a commit and returns an {@link RpcResult} of + * rollback.
    + *
  • Broker returns a error result to the consumer. + * + * + *

    Registration of functionality

    + * The registration could be done by : + *
      + *
    • returning an instance of implementation in the return value of + * {@link Provider#getProviderFunctionality()} + *
    • passing an instance of implementation and {@link DataStoreIdentifier} of + * rpc as arguments to the + * {@link DataProviderService#addCommitHandler(DataStoreIdentifier, DataCommitHandler)} + *
    + * + * + */ +public interface DataCommitHandler extends Provider.ProviderFunctionality { + + /** + * A set of Data Stores supported by implementation. + * + * The set of {@link DataStoreIdentifier}s which identifies target data + * stores which are supported by this commit handler. This set is used, when + * {@link Provider} is registered to the SAL, to register and expose the + * commit handler functionality to affected data stores. + * + * @return Set of Data Store identifiers + */ + Set getSupportedDataStores(); + + /** + * The provider (commit handler) starts a commit transaction. + * + *

    + * The commit handler (provider) prepares an commit scenario, rollback + * scenario and validates data. + * + *

    + * If the provider is aware that at this point the commit would not be + * successful, the transaction is not created, but list of errors which + * prevented the start of transaction are returned. + * + * @param store + * @return Transaction object representing this commit, errors otherwise. + */ + RpcResult requestCommit(DataStoreIdentifier store); + + public interface CommitTransaction { + /** + * + * @return Data store affected by the transaction + */ + DataStoreIdentifier getDataStore(); + + /** + * Returns the handler associated with this transaction. + * + * @return Handler + */ + DataCommitHandler getHandler(); + + /** + * + * Finishes a commit. + * + * The provider (commit handler) should apply all changes to its state + * which are a result of data change- + * + * @return + */ + RpcResult finish() throws IllegalStateException; + + /** + * Rollbacks a commit. + * + * @return + * @throws IllegalStateException + * If the method is invoked after {@link #finish()} + */ + RpcResult rollback() throws IllegalStateException; + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java new file mode 100644 index 0000000000..5c5423d80f --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java @@ -0,0 +1,78 @@ +/* + * 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.controller.sal.core.api.data; + +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.sal.core.api.Provider; + +public interface DataProviderService extends DataBrokerService { + + /** + * Adds {@link DataValidator} for specified Data Store + * + * @param store + * Data Store + * @param validator + * Validator + */ + public void addValidator(DataStoreIdentifier store, DataValidator validator); + + /** + * Removes {@link DataValidator} from specified Data Store + * + * @param store + * @param validator + * Validator + */ + public void removeValidator(DataStoreIdentifier store, + DataValidator validator); + + /** + * Adds {@link DataCommitHandler} for specified data store + * + * @param store + * @param provider + */ + void addCommitHandler(DataStoreIdentifier store, DataCommitHandler provider); + + /** + * Removes {@link DataCommitHandler} from specified data store + * + * @param store + * @param provider + */ + void removeCommitHandler(DataStoreIdentifier store, + DataCommitHandler provider); + + /** + * Adds {@link DataRefresher} for specified data store + * + * @param store + * @param refresher + */ + void addRefresher(DataStoreIdentifier store, DataRefresher refresher); + + /** + * Removes {@link DataRefresher} from specified data store + * + * @param store + * @param refresher + */ + void removeRefresher(DataStoreIdentifier store, DataRefresher refresher); + + public interface DataRefresher extends Provider.ProviderFunctionality { + + /** + * Fired when some component explicitly requested the data refresh. + * + * The provider which exposed the {@link DataRefresher} should republish + * its provided data by editing the data in all affected data stores. + */ + void refreshData(); + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataValidator.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataValidator.java new file mode 100644 index 0000000000..a2105b41d7 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataValidator.java @@ -0,0 +1,57 @@ +/* + * 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.controller.sal.core.api.data; + +import java.util.Set; + +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.yang.common.RpcResult; +import org.opendaylight.controller.yang.data.api.CompositeNode; + + +/** + * {@link Provider}-supplied Validator of the data. + * + *

    + * The registration could be done by : + *

      + *
    • returning an instance of implementation in the return value of + * {@link Provider#getProviderFunctionality()} + *
    • passing an instance of implementation and {@link DataStoreIdentifier} rpc + * as arguments to the + * {@link DataProviderService#addValidator(DataStoreIdentifier, DataValidator)} + *
    + * + **/ +public interface DataValidator extends Provider.ProviderFunctionality { + + /** + * A set of Data Stores supported by implementation. + * + * The set of {@link DataStoreIdentifier}s which identifies target data + * stores which are supported by this implementation. This set is used, when + * {@link Provider} is registered to the SAL, to register and expose the + * validation functionality to affected data stores. + * + * @return Set of Data Store identifiers + */ + Set getSupportedDataStores(); + + /** + * Performs validation on supplied data. + * + * @param toValidate + * Data to validate + * @return Validation result. The + * {@link RpcResult#isSuccessful()} == true if the data + * passed validation, otherwise contains list of errors. + */ + RpcResult validate(CompositeNode toValidate); + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/package-info.java new file mode 100644 index 0000000000..b58659a726 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/data/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.core.api.data; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationListener.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationListener.java new file mode 100644 index 0000000000..5f72c62805 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationListener.java @@ -0,0 +1,42 @@ +/* + * 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.controller.sal.core.api.notify; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.Consumer; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; + + +/** + * Notification listener for SAL notifications. + */ +public interface NotificationListener extends Consumer.ConsumerFunctionality { + /** + * A set of notification types supported by listeners. + * + * The set of notification {@link QName}s which are supported by this + * listener. This set is used, when {@link Consumer} is registered to the + * SAL, to automatically register the listener. + * + * @return Set of QNames identifying supported notifications. + */ + Set getSupportedNotifications(); + + /** + * Fired when the notification occurs. + * + * The type of the notification could be learned by + * QName type = notification.getNodeType(); + * + * @param notification + * Notification content + */ + void onNotification(CompositeNode notification); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationProviderService.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationProviderService.java new file mode 100644 index 0000000000..9367645d4c --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationProviderService.java @@ -0,0 +1,47 @@ +/* + * 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.controller.sal.core.api.notify; + +import org.opendaylight.controller.sal.core.api.Broker; +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.yang.data.api.CompositeNode; + + +/** + * Notification Publishing Service + * + * The simplified process of the notification publishing is following: + * + *
      + *
    1. {@link Provider} invokes {@link #sendNotification(CompositeNode)} + *
    2. {@link Broker} finds {@link NotificationListener}s which subscribed for + * the notification type. + * + *
    3. For each subscriber {@link Broker} invokes + * {@link NotificationListener#onNotification(CompositeNode)} + *
    + * + * + * + */ +public interface NotificationProviderService extends BrokerService { + + /** + * Publishes a notification. + * + * Notification type is determined by the + * {@link CompositeNode#getNodeType()} of the + * notification parameter. + * + * @param notification + * Notification to publish + */ + void sendNotification(CompositeNode notification); + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationService.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationService.java new file mode 100644 index 0000000000..98a4925afb --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/NotificationService.java @@ -0,0 +1,54 @@ +/* + * 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.controller.sal.core.api.notify; + +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.yang.common.QName; + + +/** + * NotificationService provides access to the notification functionality of the + * SAL. + * + * NotificationService allows for consumption of notifications by registering + * implementations of NotificationListener. + * + * The registration of notification listeners could be done by: + *
      + *
    • returning an instance of implementation in the return value of + * {@link Provider#getProviderFunctionality()} + *
    • passing an instance of implementation and {@link QName} of rpc as an + * arguments to the + * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)} + *
    + * + * + */ +public interface NotificationService extends BrokerService { + + /** + * Registers a notification listener for supplied notification type. + * + * @param notification + * @param listener + */ + void addNotificationListener(QName notification, + NotificationListener listener); + + /** + * Removes a notification listener for supplied notification type. + * + * @param notification + * @param listener + */ + void removeNotificationListener(QName notification, + NotificationListener listener); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/package-info.java new file mode 100644 index 0000000000..b6868340bb --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/notify/package-info.java @@ -0,0 +1,11 @@ +/* + * 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 + */ +/** + * SAL Notification functionality + */ +package org.opendaylight.controller.sal.core.api.notify; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/package-info.java new file mode 100644 index 0000000000..a058df363d --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-api/src/main/java/org/opendaylight/controller/sal/core/api/package-info.java @@ -0,0 +1,11 @@ +/* + * 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 + */ +/** + * Core binding-independent SAL contracts and components + */ +package org.opendaylight.controller.sal.core.api; diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-demo/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-core-demo/pom.xml new file mode 100644 index 0000000000..91dd78c144 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-demo/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-core-demo + + + + + org.opendaylight.controller + sal-broker-impl + 1.0-SNAPSHOT + + + org.opendaylight.controller + yang-data-util + 1.0 + + + org.slf4j + slf4j-simple + 1.7.2 + runtime + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoConsumerImpl.java b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoConsumerImpl.java new file mode 100644 index 0000000000..e0752dca02 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoConsumerImpl.java @@ -0,0 +1,107 @@ +/* + * 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.controller.sal.demo; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.Consumer; +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.controller.sal.core.api.notify.NotificationService; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class DemoConsumerImpl implements Consumer { + + private ConsumerSession session; + private NotificationService notificationService; + private final String name; + private static Logger log = LoggerFactory.getLogger("AlertLogger"); + + private boolean changeAware; + + public DemoConsumerImpl(String name) { + this.name = name; + } + + private NotificationListener alertLogger = new NotificationListener() { + + @Override + public void onNotification(CompositeNode notification) { + System.out.println(name + + ": Received alert: " + + notification.getFirstSimpleByName( + DemoUtils.contentNodeName).getValue()); + log.info("AlertLogger: Received notification: " + notification); + } + + @Override + public Set getSupportedNotifications() { + Set supported = new HashSet(); + supported.add(DemoUtils.alertNotification); + return supported; + } + }; + + private NotificationListener changeLogger = new NotificationListener() { + + @Override + public void onNotification(CompositeNode notification) { + System.out.println(name + + ": Received change: " + + notification.getFirstSimpleByName( + DemoUtils.contentNodeName).getValue()); + log.info("ChangeLogger: Received notification: " + notification); + } + + @Override + public Set getSupportedNotifications() { + Set supported = new HashSet(); + supported.add(DemoUtils.alertNotification); + return supported; + } + }; + + @Override + public void onSessionInitiated(ConsumerSession session) { + this.session = session; + this.notificationService = session + .getService(NotificationService.class); + notificationService.addNotificationListener( + DemoUtils.alertNotification, alertLogger); + if (isChangeAware()) { + notificationService.addNotificationListener( + DemoUtils.changeNotification, changeLogger); + } + } + + @Override + public Collection getConsumerFunctionality() { + Set func = new HashSet(); + func.add(alertLogger); + return func; + } + + public void closeSession() { + session.close(); + } + + public boolean isChangeAware() { + return changeAware; + } + + public void setChangeAware(boolean changeAware) { + this.changeAware = changeAware; + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoProviderImpl.java b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoProviderImpl.java new file mode 100644 index 0000000000..2cb04e1aaf --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoProviderImpl.java @@ -0,0 +1,69 @@ +/* + * 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.controller.sal.demo; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.data.util.Nodes; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.sal.core.api.notify.NotificationProviderService; +import org.opendaylight.controller.yang.data.api.Node; + + +public class DemoProviderImpl implements + org.opendaylight.controller.sal.core.api.Provider { + + private ProviderSession session; + private NotificationProviderService notifier; + + @Override + public void onSessionInitiated(ProviderSession session) { + this.session = session; + notifier = session.getService(NotificationProviderService.class); + } + + @Override + public Collection getProviderFunctionality() { + return Collections.emptySet(); + } + + public void sendAlertNotification(String content) { + List> nodes = new ArrayList>(); + nodes.add(DemoUtils.contentNode(content)); + + if (notifier == null) { + System.out.println("Provider: Error: Session not available"); + System.out + .println(" Notification Service not available"); + return; + } + notifier.sendNotification(Nodes.containerNode( + DemoUtils.alertNotification, nodes)); + } + + public void sendChangeNotification(String content) { + List> nodes = new ArrayList>(); + nodes.add(DemoUtils.contentNode(content)); + + if (notifier == null) { + System.out.println("Provider: Error: Session not available"); + System.out + .println(" Notification Service not available"); + return; + } + notifier.sendNotification(Nodes.containerNode( + DemoUtils.changeNotification, nodes)); + } + + public void closeSession() { + session.close(); + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoUtils.java b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoUtils.java new file mode 100644 index 0000000000..ffc06a50c5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/DemoUtils.java @@ -0,0 +1,44 @@ +/* + * 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.controller.sal.demo; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Date; + +import org.opendaylight.controller.data.util.Nodes; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.Node; + + +public class DemoUtils { + + public static final URI namespace = uri("urn:cisco:prototype:sal:demo"); + public static final Date revision = new Date(); + + public static final QName alertNotification = qName("alert"); + public static final QName changeNotification = qName("change"); + + public static final QName contentNodeName = qName("content"); + + public static URI uri(String str) { + try { + return new URI(str); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + public static QName qName(String str) { + return new QName(namespace, revision, str); + } + + public static Node contentNode(String content) { + return Nodes.leafNode(contentNodeName, content); + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/SALDemo.java b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/SALDemo.java new file mode 100644 index 0000000000..b582349f54 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/SALDemo.java @@ -0,0 +1,154 @@ +/* + * 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.controller.sal.demo; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.opendaylight.controller.sal.core.impl.BrokerImpl; +import org.opendaylight.controller.sal.core.impl.notify.NotificationModule; + + +public class SALDemo { + + static BrokerImpl broker; + static DemoProviderImpl provider; + static DemoConsumerImpl consumer1; + static DemoConsumerImpl consumer2; + + public static void main(String[] args) { + + initialize(); + initializeProvider(); + displayHelp(); + + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + String s; + try { + while (true) { + + System.out.print("\nEnter your choice (0 - list): "); + s = in.readLine(); + int choice = Integer.parseInt(s.trim()); + try { + switch (choice) { + case 0: + displayHelp(); + break; + case 1: + registerProvider(); + break; + case 2: + registerConsumer1(); + break; + case 3: + registerConsumer2(); + break; + case 4: + sendAlert(in); + break; + case 5: + sendChange(in); + break; + case 6: + unregisterConsumer1(); + break; + case 7: + unregisterConsumer2(); + break; + case 8: + unregisterProvider(); + break; + case 9: + return; + default: + System.out.println("Please enter valid input."); + break; + } + } catch (Exception e) { + System.out + .println("Operation failed. Reason exception raised: " + + e.getClass().getSimpleName()); + System.out.println(" Message: " + e.getMessage()); + } + + } + } catch (IOException e) { + + e.printStackTrace(); + } + } + + private static void registerConsumer1() { + broker.registerConsumer(consumer1); + } + + private static void registerConsumer2() { + broker.registerConsumer(consumer2); + } + + private static void sendAlert(BufferedReader in) throws IOException { + System.out.print("Please enter notification content:"); + String content = in.readLine(); + provider.sendAlertNotification(content); + } + + private static void sendChange(BufferedReader in) throws IOException { + System.out.print("Please enter notification content:"); + String content = in.readLine(); + provider.sendChangeNotification(content); + } + + private static void unregisterConsumer1() { + consumer1.closeSession(); + } + + private static void unregisterConsumer2() { + consumer2.closeSession(); + } + + private static void unregisterProvider() { + provider.closeSession(); + } + + private static void displayHelp() { + System.out.println("Usage: "); + System.out.println(" 0) Display Help"); + System.out.println(" 1) Register Provider"); + System.out.println(" 2) Register Consumer 1 (listening on alert)"); + System.out + .println(" 3) Register Consumer 2 (listening on alert,change)"); + System.out.println(" 4) Send Alert Notification"); + System.out.println(" 5) Send Change Notification"); + System.out.println(" 6) Unregister Consumer 1"); + System.out.println(" 7) Unregister Consumer 2"); + System.out.println(" 8) Unregister Provider"); + System.out.println(" 9) Exit"); + + } + + private static void initializeProvider() { + provider = new DemoProviderImpl(); + } + + private static void initialize() { + System.out.println("Initializing broker"); + broker = new BrokerImpl(); + NotificationModule notifyModule = new NotificationModule(); + broker.addModule(notifyModule); + + consumer1 = new DemoConsumerImpl("Consumer 1"); + consumer2 = new DemoConsumerImpl("Consumer 2"); + consumer2.setChangeAware(true); + } + + private static void registerProvider() { + broker.registerProvider(provider); + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/package-info.java new file mode 100644 index 0000000000..09d4bfb8e4 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-demo/src/main/java/org/opendaylight/controller/sal/demo/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.demo; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-spi/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-core-spi/pom.xml new file mode 100644 index 0000000000..3378a36fbc --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-spi/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-core-spi + + + + org.opendaylight.controller + sal-core-api + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-spi/src/main/java/org/opendaylight/controller/sal/core/spi/BrokerModule.java b/opendaylight/sal/yang-prototype/sal/sal-core-spi/src/main/java/org/opendaylight/controller/sal/core/spi/BrokerModule.java new file mode 100644 index 0000000000..99438c86b8 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-spi/src/main/java/org/opendaylight/controller/sal/core/spi/BrokerModule.java @@ -0,0 +1,27 @@ +/* + * 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.controller.sal.core.spi; + +import java.util.Set; + +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession; +import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality; +import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality; + +public interface BrokerModule { + + Set> getProvidedServices(); + + Set> getSupportedConsumerFunctionality(); + + T getServiceForSession(Class service, + ConsumerSession session); + + Set> getSupportedProviderFunctionality(); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-core-spi/src/main/java/org/opendaylight/controller/sal/core/spi/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-core-spi/src/main/java/org/opendaylight/controller/sal/core/spi/package-info.java new file mode 100644 index 0000000000..76493afd18 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-core-spi/src/main/java/org/opendaylight/controller/sal/core/spi/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.core.spi; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-data-api/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-data-api/pom.xml new file mode 100644 index 0000000000..74230e5f7c --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-data-api/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-data-api + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/.gitignore b/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/.gitignore @@ -0,0 +1 @@ +/target diff --git a/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/pom.xml new file mode 100644 index 0000000000..db0ee84c47 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/pom.xml @@ -0,0 +1,16 @@ + + 4.0.0 + + org.opendaylight.controller + sal + 1.0-SNAPSHOT + + sal-schema-repository-api + + + org.opendaylight.controller + yang-model-api + 1.0 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/src/main/java/org/opendaylight/controller/sal/schema/api/SchemaContext.java b/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/src/main/java/org/opendaylight/controller/sal/schema/api/SchemaContext.java new file mode 100644 index 0000000000..009b21cf25 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/src/main/java/org/opendaylight/controller/sal/schema/api/SchemaContext.java @@ -0,0 +1,30 @@ +/* + * 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.controller.sal.schema.api; + +import java.util.Set; + +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.NotificationDefinition; +import org.opendaylight.controller.yang.model.api.RpcDefinition; + + +/** + * + */ +public interface SchemaContext { + + Set getDataDefinitions(); + + Set getModules(); + + Set getNotifications(); + + Set getOperations(); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/src/main/java/org/opendaylight/controller/sal/schema/api/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/src/main/java/org/opendaylight/controller/sal/schema/api/package-info.java new file mode 100644 index 0000000000..39387f1414 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-schema-repository-api/src/main/java/org/opendaylight/controller/sal/schema/api/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.sal.schema.api; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/pom.xml b/opendaylight/sal/yang-prototype/yang/pom.xml new file mode 100644 index 0000000000..d10366c2cf --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/pom.xml @@ -0,0 +1,84 @@ + + 4.0.0 + org.opendaylight.controller + yang + 1.0 + pom + + yang-common + yang-data-api + yang-data-util + yang-model-api + yang-model-util + yang-binding + + + + + junit + junit + 4.10 + test + true + + + org.slf4j + slf4j-api + 1.7.2 + + + org.slf4j + slf4j-simple + 1.7.2 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0 + true + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + maven + + + + + aggregate + + site + + + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 2.4.0 + + Max + Low + site + + + + org.codehaus.mojo + jdepend-maven-plugin + 2.0-beta-2 + + + + diff --git a/opendaylight/sal/yang-prototype/yang/yang-binding/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-binding/pom.xml new file mode 100644 index 0000000000..3ddd4b37fc --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-binding/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + + org.opendaylight.controller + yang + 1.0 + + yang-binding + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/DataRoot.java b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/DataRoot.java new file mode 100644 index 0000000000..2f194b2bbe --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/DataRoot.java @@ -0,0 +1,16 @@ +/* + * 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.controller.yang.binding; + +/** + * + * + */ +public interface DataRoot { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/Notification.java b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/Notification.java new file mode 100644 index 0000000000..9b8c1cff02 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/Notification.java @@ -0,0 +1,17 @@ +/* + * 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.controller.yang.binding; + +/** + * Marker interface for YANG-defined notifications + * + * + */ +public interface Notification { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/NotificationListener.java b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/NotificationListener.java new file mode 100644 index 0000000000..a60d2f34f9 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/NotificationListener.java @@ -0,0 +1,18 @@ +/* + * 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.controller.yang.binding; + +/** + * Marker interface for generated notification listener interfaces + * + * + * + */ +public interface NotificationListener { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/RpcService.java b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/RpcService.java new file mode 100644 index 0000000000..20f7e78aec --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/RpcService.java @@ -0,0 +1,16 @@ +/* + * 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.controller.yang.binding; + +/** + * Marker interface for tagging generated YANG Modules + * + */ +public interface RpcService { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/package-info.java b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/package-info.java new file mode 100644 index 0000000000..5ed5649c78 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-binding/src/main/java/org/opendaylight/controller/yang/binding/package-info.java @@ -0,0 +1,8 @@ +/* + * 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.controller.yang.binding; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-common/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-common/pom.xml new file mode 100644 index 0000000000..b072ab3c1b --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-common/pom.xml @@ -0,0 +1,9 @@ + + 4.0.0 + + org.opendaylight.controller + yang + 1.0 + + yang-common + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/QName.java b/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/QName.java new file mode 100644 index 0000000000..b1127204fb --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/QName.java @@ -0,0 +1,222 @@ +/* + * 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.controller.yang.common; + +import java.net.URI; +import java.net.URISyntaxException; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * The QName from XML consists of local name of element and XML namespace, but + * for our use, we added module revision to it. + * + * In YANG context QName is full name of defined node, type, procedure or + * notification. QName consists of XML namespace, YANG model revision and local + * name of defined type. It is used to prevent name clashes between nodes with + * same local name, but from different schemas. + * + *
      + *
    • XMLNamespace - the namespace assigned to the YANG module which + * defined element, type, procedure or notification.
    • + *
    • Revision - the revision of the YANG module which describes the + * element
    • + *
    • LocalName - the YANG schema identifier which were defined for this + * node in the YANG module
    • + *
    + * + * + */ +public class QName { + + private SimpleDateFormat revisionFormat = new SimpleDateFormat("yyyy-MM-dd"); + + final URI namespace; + final String localName; + final String prefix; + final Date revision; + + /** + * QName Constructor. + * + * @param namespace + * the namespace assigned to the YANG module + * @param revision + * the revision of the YANG module + * @param prefix + * locally defined prefix assigned to local name + * @param localName + * YANG schema identifier + */ + public QName(URI namespace, Date revision, String prefix, String localName) { + this.namespace = namespace; + this.localName = localName; + this.revision = revision; + this.prefix = prefix; + } + + /** + * QName Constructor. + * + * @param namespace + * the namespace assigned to the YANG module + * @param localName + * YANG schema identifier + */ + public QName(URI namespace, String localName) { + this(namespace, null, "", localName); + } + + /** + * QName Constructor. + * + * @param namespace + * the namespace assigned to the YANG module + * @param revision + * the revision of the YANG module + * @param localName + * YANG schema identifier + */ + public QName(URI namespace, Date revision, String localName) { + this(namespace, revision, null, localName); + } + + public QName(QName base, String localName) { + this(base.getNamespace(), base.getRevision(), base.getPrefix(), + localName); + } + + /** + * Returns XMLNamespace assigned to the YANG module. + * + * @return XMLNamespace assigned to the YANG module. + */ + public URI getNamespace() { + return namespace; + } + + /** + * Returns YANG schema identifier which were defined for this node in the + * YANG module + * + * @return YANG schema identifier which were defined for this node in the + * YANG module + */ + public String getLocalName() { + return localName; + } + + /** + * Returns revision of the YANG module if the module has defined revision, + * otherwise returns null + * + * @return revision of the YANG module if the module has defined revision, + * otherwise returns null + */ + public Date getRevision() { + return revision; + } + + /** + * Returns locally defined prefix assigned to local name + * + * @return locally defined prefix assigned to local name + */ + public String getPrefix() { + return prefix; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((localName == null) ? 0 : localName.hashCode()); + result = prime * result + + ((namespace == null) ? 0 : namespace.hashCode()); + result = prime * result + + ((revision == null) ? 0 : revision.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + QName other = (QName) obj; + if (localName == null) { + if (other.localName != null) + return false; + } else if (!localName.equals(other.localName)) + return false; + if (namespace == null) { + if (other.namespace != null) + return false; + } else if (!namespace.equals(other.namespace)) + return false; + if (revision == null) { + if (other.revision != null) + return false; + } else if (!revision.equals(other.revision)) + return false; + return true; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (namespace != null) { + sb.append("(" + namespace); + + if (revision != null) { + sb.append("?revision=" + revisionFormat.format(revision)); + } + sb.append(")"); + } + sb.append(localName); + return sb.toString(); + } + + /** + * Returns a namespace in form defined by section 5.6.4. of {@link https + * ://tools.ietf.org/html/rfc6020}, if namespace is not correctly defined, + * the method will return null
    + * example "http://example.acme.com/system?revision=2008-04-01" + * + * @return namespace in form defined by section 5.6.4. of {@link https + * ://tools.ietf.org/html/rfc6020}, if namespace is not correctly + * defined, the method will return null + * + */ + URI getRevisionNamespace() { + + if (namespace == null) + return null; + + String query = ""; + if (revision != null) { + query = "revision=" + revisionFormat.format(revision); + } + + URI compositeURI = null; + try { + compositeURI = new URI(namespace.getScheme(), + namespace.getUserInfo(), namespace.getHost(), + namespace.getPort(), namespace.getPath(), query, + namespace.getFragment()); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + return compositeURI; + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/RpcError.java b/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/RpcError.java new file mode 100644 index 0000000000..cb819297a0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/RpcError.java @@ -0,0 +1,32 @@ +/* + * 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.controller.yang.common; + +//import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; + +public interface RpcError { + ErrorSeverity getSeverity(); + + String getTag(); + + String getApplicationTag(); + + String getMessage(); + + String getInfo(); + + // RevisionAwareXPath getPath(); + + public enum ErrorSeverity { + ERROR, WARNING, + } + + public enum ErrorType { + TRANSPORT, RPC, PROTOCOL, APPLICATION + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/RpcResult.java b/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/RpcResult.java new file mode 100644 index 0000000000..d754cb710b --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-common/src/main/java/org/opendaylight/controller/yang/common/RpcResult.java @@ -0,0 +1,18 @@ +/* + * 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.controller.yang.common; + +import java.util.Collection; + +public interface RpcResult { + boolean isSuccessful(); + + T getResult(); + + Collection getErrors(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-data-api/pom.xml new file mode 100644 index 0000000000..358cabd2d5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + + org.opendaylight.controller + yang + 1.0 + + yang-data-api + + + + + org.opendaylight.controller + yang-common + 1.0 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNode.java new file mode 100644 index 0000000000..dfc790e0bd --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNode.java @@ -0,0 +1,48 @@ +/* + * 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.controller.yang.data.api; + +import java.util.List; + +import org.opendaylight.controller.yang.common.QName; + +/** + * Composite node represents a branch in the data tree, which could contain + * nested composite nodes or leaf nodes. In the terms of the XML the simple node + * is element which does not text data directly (CDATA or PCDATA), only other + * nodes. The composite node is the manifestation of the following data schema + * constructs in the YANG: + * + *
      + *
    • container - the composite node represents the YANG container and + * could contain all children schema nodes of that container
    • + *
    • item in the list - the composite node represents one item + * in the YANG list and could contain all children schema nodes of that list + * item.
    • + *
    • anyxml
    • + *
    + * + * + */ +public interface CompositeNode extends Node>> { + + List> getChildren(); + + List getCompositesByName(QName children); + + List getCompositesByName(String children); + + List> getSimpleNodesByName(QName children); + + List> getSimpleNodesByName(String children); + + CompositeNode getFirstCompositeByName(QName container); + + SimpleNode getFirstSimpleByName(QName leaf); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java new file mode 100644 index 0000000000..1772ddf3be --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/CompositeNodeModification.java @@ -0,0 +1,110 @@ +/* + * 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.controller.yang.data.api; + +import org.opendaylight.controller.yang.common.QName; + +/** + * For the use cases of changing the state data, the node modifications are + * modeled as part of additional metadata in data tree. The modification types + * are based on Netconf edit-config RPCs. In order to modify the configuration + * or state data tree the user must create a tree representing the modification + * of the data and apply that modification to the target tree. + * + * + * @see Network Configuration + * Protocol (NETCONF) + * + */ +public interface CompositeNodeModification extends CompositeNode { + + ModifyAction getModificationAction(); + + // Container Modification + + /** + * The data identified by the node containing this modification is merged + * with the data at the corresponding level in the data tree + * + * @param node + * in data tree + */ + void mergeChild(CompositeNode node); + + /** + * The data identified by the node containing this modification replaces any + * related data in the target data tree If no such data exists in the target + * data tree, the child node is created. + * + * @param node + * composite node + */ + void replaceChild(CompositeNode node); + + /** + * Adds new composite node into data tree + * + * @param node + * composite node + */ + void addChild(CompositeNode node); + + /** + * The data identified by the node containing this modification is deleted + * from the target data tree if and only if the data currently exists in the + * target data tree. If the data does not exist, an error is returned with + * an error value of "data-missing". + * + * @param node + */ + void deleteChild(CompositeNode node); + + /** + * The data identified by the node containing this attribute is deleted from + * the target data tree if the data currently exists in the target data + * tree. If the data does not exist, the modification is silently ignored. + * + * @param node + * composite node + */ + void removeChild(CompositeNode node); + + // Leaf Modifications + + /** + * The data identified by the node containing this modification replaces any + * related data in the target data tree If no such data exists in the target + * data tree, it is created. + * + * @param leaf + */ + void replaceSimpleNode(SimpleNode leaf); + + /** + * The data identified by the node containing this modification is deleted + * from the target data tree if and only if the data currently exists in the + * target data tree. If the data does not exist, an error is returned with + * an error value of "data-missing". + * + * @param leaf + */ + void deleteSimpleNode(SimpleNode leaf); + + /** + * The data identified by the node containing this attribute is deleted from + * the target data tree if the data currently exists in the target data + * tree. If the data does not exist, the modification is silently ignored. + * + * @param leaf + */ + void removeSimpleNode(SimpleNode leaf); + + void removeLeaf(SimpleNode leaf); + + void removeLeaf(QName leaf); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/ModifyAction.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/ModifyAction.java new file mode 100644 index 0000000000..fa17043387 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/ModifyAction.java @@ -0,0 +1,12 @@ +/* + * 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.controller.yang.data.api; + +public enum ModifyAction { + MERGE, REPLACE, CREATE, DELETE, REMOVE +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/Node.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/Node.java new file mode 100644 index 0000000000..341a2866f0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/Node.java @@ -0,0 +1,42 @@ +/* + * 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.controller.yang.data.api; + +import org.opendaylight.controller.yang.common.QName; + +/** + * Base representation of node in the data tree, defines basic parameters of + * node such as a QName. + * + * + * @param + */ +public interface Node { + + /** + * Returns the name of the Node + * + * @return + */ + QName getNodeType(); + + /** + * Returns parent node + * + * @return parent node + */ + CompositeNode getParent(); + + /** + * Returns the value that holds current node, if no value is defined method + * can return null + * + * @return Returns the value that holds current node. + */ + T getValue(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/SimpleNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/SimpleNode.java new file mode 100644 index 0000000000..717c7224ee --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-api/src/main/java/org/opendaylight/controller/yang/data/api/SimpleNode.java @@ -0,0 +1,26 @@ +/* + * 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.controller.yang.data.api; + +/** + * Simple node represents a leaf in the data tree, which does not contain any + * nested nodes, but the value of node. In the terms of the XML the simple node + * is element which contains only text data (CDATA or PCDATA). The simple node + * is the manifestation of the following data schema constructs in YANG: + *
      + *
    • leaf - simple node could represent YANG leafs of all types except + * the empty type, which in XML form is similar to the empty container.
    • + *
    • item in leaf-list
    • + *
    + * + * + * @param + */ +public interface SimpleNode extends Node { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-util/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-data-util/pom.xml new file mode 100644 index 0000000000..2595d5d8a7 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-util/pom.xml @@ -0,0 +1,16 @@ + + 4.0.0 + + org.opendaylight.controller + yang + 1.0 + + yang-data-util + + + org.opendaylight.controller + yang-data-api + 1.0 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/AbstractContainerNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/AbstractContainerNode.java new file mode 100644 index 0000000000..7a5cfda6de --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/AbstractContainerNode.java @@ -0,0 +1,108 @@ +/* + * 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.controller.data.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.SimpleNode; + +public abstract class AbstractContainerNode extends AbstractNode>> + implements CompositeNode { + + public SimpleNode getFirstSimpleByName(QName leaf) { + List> list = getSimpleNodesByName(leaf); + if (list.size() == 0) + return null; + return list.get(0); + } + + protected AbstractContainerNode(QName name, CompositeNode parent) { + super(name, parent); + } + + public AbstractContainerNode(QName name) { + super(name, null); + } + + public List> getChildren() { + return getValue(); + } + + public List> getValue() { + Map>> map = getNodeMap(); + if (map == null) + throw new IllegalStateException("nodeMap should not be null"); + List> ret = new ArrayList>(); + Collection>> values = map.values(); + for (List> list : values) { + ret.addAll(list); + } + return ret; + } + + protected abstract Map>> getNodeMap(); + + public List getCompositesByName(QName children) { + Map>> map = getNodeMap(); + if (map == null) + throw new IllegalStateException("nodeMap should not be null"); + List> toFilter = map.get(children); + List list = new ArrayList(); + for (Node node : toFilter) { + if (node instanceof CompositeNode) + list.add((CompositeNode) node); + } + return list; + } + + public List> getSimpleNodesByName(QName children) { + Map>> map = getNodeMap(); + if (map == null) + throw new IllegalStateException("nodeMap should not be null"); + List> toFilter = map.get(children); + List> list = new ArrayList>(); + + for (Node node : toFilter) { + if (node instanceof SimpleNode) + list.add((SimpleNode) node); + } + return list; + } + + public CompositeNode getFirstCompositeByName(QName container) { + List list = getCompositesByName(container); + if (list.size() == 0) + return null; + return list.get(0); + } + + public SimpleNode getFirstLeafByName(QName leaf) { + List> list = getSimpleNodesByName(leaf); + if (list.size() == 0) + return null; + return list.get(0); + } + + public List getCompositesByName(String children) { + return getCompositesByName(localQName(children)); + } + + public List> getSimpleNodesByName(String children) { + return getSimpleNodesByName(localQName(children)); + } + + private QName localQName(String str) { + return new QName(getNodeType(), str); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/AbstractNode.java b/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/AbstractNode.java new file mode 100644 index 0000000000..1f4b6aa4d7 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/AbstractNode.java @@ -0,0 +1,31 @@ +/* + * 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.controller.data.util; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.Node; + +public abstract class AbstractNode implements Node { + + private final QName nodeName; + private final CompositeNode parent; + + protected AbstractNode(QName name, CompositeNode parent) { + nodeName = name; + this.parent = parent; + } + + public QName getNodeType() { + return this.nodeName; + } + + public CompositeNode getParent() { + return parent; + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/Nodes.java b/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/Nodes.java new file mode 100644 index 0000000000..16d5461acf --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-data-util/src/main/java/org/opendaylight/controller/data/util/Nodes.java @@ -0,0 +1,94 @@ +/* + * 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.controller.data.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.opendaylight.controller.yang.data.api.Node; +import org.opendaylight.controller.yang.data.api.SimpleNode; + +public class Nodes { + + private Nodes() { + } + + public static SimpleNode leafNode(QName name, T value) { + return new SimpleNodeTO(name, value, null); + } + + public static CompositeNode containerNode(QName name, List> children) { + return containerNode(name, children, null); + } + + public static CompositeNode containerNode(QName name, + List> children, CompositeNode parent) { + return new ContainerNodeTO(name, parent, nodeMapFromList(children)); + } + + public static Map>> nodeMapFromList( + List> children) { + Map>> map = new HashMap>>(); + for (Node node : children) { + + QName name = node.getNodeType(); + List> targetList = map.get(name); + if (targetList == null) { + targetList = new ArrayList>(); + map.put(name, targetList); + } + targetList.add(node); + } + return map; + } + + private static class ContainerNodeTO extends AbstractContainerNode { + + private final Map>> nodeMap; + + public ContainerNodeTO(QName name, Map>> nodeMap) { + super(name); + this.nodeMap = nodeMap; + } + + public ContainerNodeTO(QName name, CompositeNode parent, + Map>> nodeMap) { + super(name, parent); + this.nodeMap = nodeMap; + } + + @Override + protected Map>> getNodeMap() { + + return nodeMap; + } + } + + private static class SimpleNodeTO extends AbstractNode implements + SimpleNode { + + private final T value; + + protected SimpleNodeTO(QName name, T val, CompositeNode parent) { + super(name, parent); + value = val; + + } + + @Override + public T getValue() { + return value; + } + + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-model-api/pom.xml new file mode 100644 index 0000000000..bf1a4ce76f --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + org.opendaylight.controller + yang + 1.0 + + yang-model-api + + + + org.opendaylight.controller + yang-common + 1.0 + + + \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BinaryTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BinaryTypeDefinition.java new file mode 100644 index 0000000000..babceb24d5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BinaryTypeDefinition.java @@ -0,0 +1,33 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +/** + * The binary built-in type represents any binary data, i.e., a sequence of + * octets.
    + *
    + * Binary values are encoded with the base64 encoding scheme (see [RFC4648], Section + * 4).
    + * The canonical form of a binary value follows the rules in [RFC4648]. + * + * + */ +public interface BinaryTypeDefinition extends + TypeDefinition { + + /** + * Returns the number of octets it that binary value contains. + * + * @return the number of octets it that binary value contains. + */ + public LengthConstraint getLengthConstraint(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BitsTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BitsTypeDefinition.java new file mode 100644 index 0000000000..84fbf593c0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BitsTypeDefinition.java @@ -0,0 +1,30 @@ +/* + * 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.controller.model.api.type; + +import java.util.List; + +import org.opendaylight.controller.yang.model.api.SchemaNode; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface BitsTypeDefinition extends TypeDefinition { + + public List getBits(); + + interface Bit extends SchemaNode { + /** + * The position value MUST be in the range 0 to 4294967295, and it MUST + * be unique within the bits type. + * + * @return The position value of bit in range from 0 to 4294967295. + */ + public Long getPosition(); + + public String getName(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BooleanTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BooleanTypeDefinition.java new file mode 100644 index 0000000000..84c3e80d2a --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/BooleanTypeDefinition.java @@ -0,0 +1,15 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface BooleanTypeDefinition extends + TypeDefinition { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/DecimalTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/DecimalTypeDefinition.java new file mode 100644 index 0000000000..78ca2ac347 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/DecimalTypeDefinition.java @@ -0,0 +1,31 @@ +/* + * 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.controller.model.api.type; + +import java.util.List; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface DecimalTypeDefinition extends + TypeDefinition { + + List getRangeStatements(); + + /** + * Returns integer between 1 and 18 inclusively.
    + *
    + * + * The "fraction-digits" statement controls the size of the minimum + * difference between values of a decimal64 type, by restricting the value + * space to numbers that are expressible as "i x 10^-n" where n is the + * fraction-digits argument. + * + * @return + */ + Integer getFractionDigits(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/EmptyTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/EmptyTypeDefinition.java new file mode 100644 index 0000000000..77912aecb4 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/EmptyTypeDefinition.java @@ -0,0 +1,15 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface EmptyTypeDefinition extends + TypeDefinition { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/EnumTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/EnumTypeDefinition.java new file mode 100644 index 0000000000..882bb4ec99 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/EnumTypeDefinition.java @@ -0,0 +1,38 @@ +/* + * 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.controller.model.api.type; + +import java.util.List; + +import org.opendaylight.controller.yang.model.api.SchemaNode; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface EnumTypeDefinition extends TypeDefinition { + + List getValues(); + + interface EnumPair extends SchemaNode { + + /** + * The name to specify each assigned name of an enumeration type. + * + * @return name of each assigned name of an enumeration type. + */ + public String getName(); + + /** + * The "value" statement, which is optional, is used to associate an + * integer value with the assigned name for the enum. This integer value + * MUST be in the range -2147483648 to 2147483647, and it MUST be unique + * within the enumeration type. + * + * @return integer value assigned to enumeration + */ + public Integer getValue(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IdentityTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IdentityTypeDefinition.java new file mode 100644 index 0000000000..3b8abf7eb2 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IdentityTypeDefinition.java @@ -0,0 +1,17 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface IdentityTypeDefinition extends + TypeDefinition { + + public QName getIdentityName(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IdentityrefTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IdentityrefTypeDefinition.java new file mode 100644 index 0000000000..050802019f --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IdentityrefTypeDefinition.java @@ -0,0 +1,16 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface IdentityrefTypeDefinition extends + TypeDefinition { + + public IdentityTypeDefinition getIdentity(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/InstanceIdentifierTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/InstanceIdentifierTypeDefinition.java new file mode 100644 index 0000000000..44af5e0bb3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/InstanceIdentifierTypeDefinition.java @@ -0,0 +1,19 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface InstanceIdentifierTypeDefinition extends + TypeDefinition { + + public RevisionAwareXPath getPathStatement(); + + public boolean requireInstance(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IntegerTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IntegerTypeDefinition.java new file mode 100644 index 0000000000..92f3098a23 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/IntegerTypeDefinition.java @@ -0,0 +1,18 @@ +/* + * 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.controller.model.api.type; + +import java.util.List; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface IntegerTypeDefinition extends + TypeDefinition { + + List getRangeStatements(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/LeafrefTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/LeafrefTypeDefinition.java new file mode 100644 index 0000000000..ac61372994 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/LeafrefTypeDefinition.java @@ -0,0 +1,17 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface LeafrefTypeDefinition extends + TypeDefinition { + + public RevisionAwareXPath getPathStatement(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/LengthConstraint.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/LengthConstraint.java new file mode 100644 index 0000000000..8c9cb79ad0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/LengthConstraint.java @@ -0,0 +1,17 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.ConstraintMetaDefinition; + +public interface LengthConstraint extends ConstraintMetaDefinition { + + Long getMin(); + + Long getMax(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/PatternConstraint.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/PatternConstraint.java new file mode 100644 index 0000000000..c8d012b61e --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/PatternConstraint.java @@ -0,0 +1,15 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.ConstraintMetaDefinition; + +public interface PatternConstraint extends ConstraintMetaDefinition { + + public String getRegularExpression(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/RangeConstraint.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/RangeConstraint.java new file mode 100644 index 0000000000..76bfb75301 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/RangeConstraint.java @@ -0,0 +1,17 @@ +/* + * 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.controller.model.api.type; + +import org.opendaylight.controller.yang.model.api.ConstraintMetaDefinition; + +public interface RangeConstraint extends ConstraintMetaDefinition { + + Long getMin(); + + Long getMax(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/StringTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/StringTypeDefinition.java new file mode 100644 index 0000000000..2ee6d1d073 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/StringTypeDefinition.java @@ -0,0 +1,20 @@ +/* + * 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.controller.model.api.type; + +import java.util.List; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface StringTypeDefinition extends + TypeDefinition { + + List getLengthStatements(); + + List getPatterns(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnionTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnionTypeDefinition.java new file mode 100644 index 0000000000..b46e3a140b --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnionTypeDefinition.java @@ -0,0 +1,18 @@ +/* + * 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.controller.model.api.type; + +import java.util.List; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface UnionTypeDefinition extends + TypeDefinition { + + public List> getTypes(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnknownTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnknownTypeDefinition.java new file mode 100644 index 0000000000..a4da8f7a94 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnknownTypeDefinition.java @@ -0,0 +1,24 @@ +/* + * 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.controller.model.api.type; + +import java.util.List; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface UnknownTypeDefinition extends + TypeDefinition { + + public List getRangeStatements(); + + public List getLengthStatements(); + + public List getPatterns(); + + public LengthConstraint getLengthConstraint(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnsignedIntegerTypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnsignedIntegerTypeDefinition.java new file mode 100644 index 0000000000..821bb5eba6 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/model/api/type/UnsignedIntegerTypeDefinition.java @@ -0,0 +1,18 @@ +/* + * 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.controller.model.api.type; + +import java.util.List; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public interface UnsignedIntegerTypeDefinition extends + TypeDefinition { + + List getRangeStatements(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AnyXmlSchemaNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AnyXmlSchemaNode.java new file mode 100644 index 0000000000..02aaf9ca4a --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AnyXmlSchemaNode.java @@ -0,0 +1,24 @@ +/* + * 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.controller.yang.model.api; + +/** + * The "anyxml" interface defines an interior node in the schema tree. It takes + * one argument, which is an identifier represented by QName inherited from + * {@link SchemaNode}, followed by a block of substatements that holds detailed + * anyxml information. The substatements are defined in {@link DataSchemaNode}
    + *
    + * This interface was modeled according to definition in [RFC-6020] The anyxml + * Statement + * + * + */ +public interface AnyXmlSchemaNode extends DataSchemaNode { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AugmentationSchema.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AugmentationSchema.java new file mode 100644 index 0000000000..37bc9fe025 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AugmentationSchema.java @@ -0,0 +1,24 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +public interface AugmentationSchema extends DataNodeContainer { + + String getDescription(); + + String getReference(); + + Status getStatus(); + + SchemaPath getTargetPath(); + + Set getUses(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AugmentationTarget.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AugmentationTarget.java new file mode 100644 index 0000000000..77ab5a3674 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/AugmentationTarget.java @@ -0,0 +1,19 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +public interface AugmentationTarget { + /** + * Returns a set of augmentations targeting this element. + * + * @return + */ + Set getAvailableAugmentations(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceCaseNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceCaseNode.java new file mode 100644 index 0000000000..0fcbda9adc --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceCaseNode.java @@ -0,0 +1,13 @@ +/* + * 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.controller.yang.model.api; + +public interface ChoiceCaseNode extends DataSchemaNode, DataNodeContainer, + AugmentationTarget { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceNode.java new file mode 100644 index 0000000000..f289048fcb --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceNode.java @@ -0,0 +1,15 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +public interface ChoiceNode extends DataSchemaNode { + + Set getCases(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ConstraintDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ConstraintDefinition.java new file mode 100644 index 0000000000..2143324825 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ConstraintDefinition.java @@ -0,0 +1,24 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +public interface ConstraintDefinition { + DataSchemaNode getParent(); + + RevisionAwareXPath getWhenCondition(); + + Set getMustConstraints(); + + boolean isMandatory(); + + Integer getMinElements(); + + Integer getMaxElements(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ConstraintMetaDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ConstraintMetaDefinition.java new file mode 100644 index 0000000000..50f41d918d --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ConstraintMetaDefinition.java @@ -0,0 +1,19 @@ +/* + * 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.controller.yang.model.api; + +public interface ConstraintMetaDefinition { + + String getDescription(); + + String getErrorAppTag(); + + String getErrorMessage(); + + String getReference(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ContainerSchemaNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ContainerSchemaNode.java new file mode 100644 index 0000000000..27711c96f4 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ContainerSchemaNode.java @@ -0,0 +1,21 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +public interface ContainerSchemaNode extends DataNodeContainer, + AugmentationTarget, DataSchemaNode { + + Set getUses(); + + boolean isPresenceContainer(); + + MustDefinition getMustDefinition(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/DataNodeContainer.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/DataNodeContainer.java new file mode 100644 index 0000000000..8888208cc2 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/DataNodeContainer.java @@ -0,0 +1,28 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +import org.opendaylight.controller.yang.common.QName; + +public interface DataNodeContainer { + + Set> getTypeDefinitions(); + + Set getChildNodes(); + + Set getGroupings(); + + DataSchemaNode getDataChildByName(QName name); + + DataSchemaNode getDataChildByName(String name); + + Set getUses(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/DataSchemaNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/DataSchemaNode.java new file mode 100644 index 0000000000..25208aaab6 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/DataSchemaNode.java @@ -0,0 +1,36 @@ +/* + * 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.controller.yang.model.api; + +public interface DataSchemaNode extends SchemaNode { + + /** + * Returns true if the data node was added by augmentation, + * otherwise returns false + * + * @return true if the data node was added by augmentation, + * otherwise returns false + */ + boolean isAugmenting(); + + /** + * Returns true if the data represents configuration data, + * otherwise returns false + * + * @return true if the data represents configuration data, + * otherwise returns false + */ + boolean isConfiguration(); + + /** + * Returns the constraints associated with Data Schema Node + * + * @return the constraints associated with Data Schema Node + */ + ConstraintDefinition getConstraints(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Deviation.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Deviation.java new file mode 100644 index 0000000000..83510bac0f --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Deviation.java @@ -0,0 +1,24 @@ +/* + * 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.controller.yang.model.api; + +public interface Deviation { + + MustDefinition getMustDefinition(); + + enum Deviate { + NOT_SUPPORTED, ADD, REPLACE, DELETE + } + + SchemaPath getTargetPath(); + + Deviate getDeviate(); + + String getReference(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ExtensionDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ExtensionDefinition.java new file mode 100644 index 0000000000..8b2ed8679b --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ExtensionDefinition.java @@ -0,0 +1,44 @@ +/* + * 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.controller.yang.model.api; + +public interface ExtensionDefinition extends SchemaNode { + + /** + * Returns the String that is the name of argument to the + * Keyword. If no argument statement is present the method will return + * null
    + * The argument statement is defined in [RFC-6020] The + * argument Statement + * + * @return the String that is the name of argument to the + * Keyword. If no argument statement is present the method will + * return null + */ + public String getArgument(); + + /** + * This statement indicates if the argument is mapped to an XML element in + * YIN or to an XML attribute.
    + * By contract if implementation of ExtensionDefinition does not specify the + * yin-element statement the return value is by default set to + * false + * + *
    + *
    + * For more specific definition please look into [RFC-6020] + * The yin-element Statement + * + * @return true if the argument is mapped to an XML element in + * YIN or returns false if the argument is mapped to an + * XML attribute. + */ + public boolean isYinElement(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/FeatureDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/FeatureDefinition.java new file mode 100644 index 0000000000..efd0e18d18 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/FeatureDefinition.java @@ -0,0 +1,12 @@ +/* + * 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.controller.yang.model.api; + +public interface FeatureDefinition extends SchemaNode { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/GroupingDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/GroupingDefinition.java new file mode 100644 index 0000000000..5e94f3b5be --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/GroupingDefinition.java @@ -0,0 +1,16 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +public interface GroupingDefinition extends DataNodeContainer, SchemaNode { + + Set getUses(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/KeyDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/KeyDefinition.java new file mode 100644 index 0000000000..5e8b2c70a8 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/KeyDefinition.java @@ -0,0 +1,14 @@ +/* + * 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.controller.yang.model.api; + +public interface KeyDefinition extends SchemaNode { + + TypeDefinition> getType(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafListSchemaNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafListSchemaNode.java new file mode 100644 index 0000000000..2c41e19a27 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafListSchemaNode.java @@ -0,0 +1,18 @@ +/* + * 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.controller.yang.model.api; + +public interface LeafListSchemaNode extends DataSchemaNode { + + TypeDefinition> getType(); + + boolean isUserOrdered(); + + MustDefinition getMustDefinition(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafSchemaNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafSchemaNode.java new file mode 100644 index 0000000000..ccb075f7a5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/LeafSchemaNode.java @@ -0,0 +1,14 @@ +/* + * 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.controller.yang.model.api; + +public interface LeafSchemaNode extends DataSchemaNode { + TypeDefinition getType(); + + MustDefinition getMustDefinition(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ListSchemaNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ListSchemaNode.java new file mode 100644 index 0000000000..824afb76e8 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ListSchemaNode.java @@ -0,0 +1,21 @@ +/* + * 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.controller.yang.model.api; + +import java.util.List; + +import org.opendaylight.controller.yang.common.QName; + +public interface ListSchemaNode extends DataNodeContainer, AugmentationTarget, + DataSchemaNode { + + public List getKeyDefinition(); + + boolean isUserOrdered(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Module.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Module.java new file mode 100644 index 0000000000..6731844a5b --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Module.java @@ -0,0 +1,46 @@ +/* + * 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.controller.yang.model.api; + +import java.net.URI; +import java.util.Date; +import java.util.Set; + +public interface Module extends DataNodeContainer { + + URI getNamespace(); + + String getName(); + + Date getRevision(); + + String getPrefix(); + + String getYangVersion(); + + String getDescription(); + + String getReference(); + + String getOrganization(); + + String getContact(); + + Set getImports(); + + Set getFeatures(); + + Set getNotifications(); + + Set getAugmentations(); + + Set getRpcs(); + + Set getDeviations(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ModuleImport.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ModuleImport.java new file mode 100644 index 0000000000..37237dd057 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ModuleImport.java @@ -0,0 +1,19 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Date; + +public interface ModuleImport { + + String getModuleName(); + + Date getRevision(); + + String getPrefix(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/MustDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/MustDefinition.java new file mode 100644 index 0000000000..42dc39264b --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/MustDefinition.java @@ -0,0 +1,13 @@ +/* + * 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.controller.yang.model.api; + +public interface MustDefinition extends ConstraintMetaDefinition { + + RevisionAwareXPath getXpath(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/NotificationDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/NotificationDefinition.java new file mode 100644 index 0000000000..ecb25fcf7d --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/NotificationDefinition.java @@ -0,0 +1,14 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +public interface NotificationDefinition extends SchemaNode, DataNodeContainer { + Set getUses(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/RevisionAwareXPath.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/RevisionAwareXPath.java new file mode 100644 index 0000000000..df360eb43c --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/RevisionAwareXPath.java @@ -0,0 +1,12 @@ +/* + * 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.controller.yang.model.api; + +public interface RevisionAwareXPath { + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/RpcDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/RpcDefinition.java new file mode 100644 index 0000000000..a4c784e0cd --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/RpcDefinition.java @@ -0,0 +1,21 @@ +/* + * 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.controller.yang.model.api; + +import java.util.Set; + +public interface RpcDefinition extends SchemaNode { + + Set> getTypeDefinitions(); + + Set getGroupings(); + + ContainerSchemaNode getInput(); + + ContainerSchemaNode getOutput(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/SchemaNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/SchemaNode.java new file mode 100644 index 0000000000..97ca6a9585 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/SchemaNode.java @@ -0,0 +1,27 @@ +/* + * 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.controller.yang.model.api; + +import java.util.List; + +import org.opendaylight.controller.yang.common.QName; + +public interface SchemaNode { + + public QName getQName(); + + public SchemaPath getPath(); + + public String getDescription(); + + public String getReference(); + + public Status getStatus(); + + public List getExtensionSchemaNodes(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/SchemaPath.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/SchemaPath.java new file mode 100644 index 0000000000..90a5d5bc1d --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/SchemaPath.java @@ -0,0 +1,74 @@ +/* + * 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.controller.yang.model.api; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.yang.common.QName; + +public class SchemaPath { + + final List path; + final boolean absolute; + + public SchemaPath(final List path, boolean absolute) { + this.path = Collections.unmodifiableList(new ArrayList(path)); + this.absolute = absolute; + } + + public List getPath() { + return path; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (absolute ? 1231 : 1237); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + SchemaPath other = (SchemaPath) obj; + if (absolute != other.absolute) { + return false; + } + if (path == null) { + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SchemaPath [path="); + builder.append(path); + builder.append(", absolute="); + builder.append(absolute); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Status.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Status.java new file mode 100644 index 0000000000..0cb3f14149 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/Status.java @@ -0,0 +1,12 @@ +/* + * 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.controller.yang.model.api; + +public enum Status { + CURRENT, DEPRECATED, OBSOLOTE +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/TypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/TypeDefinition.java new file mode 100644 index 0000000000..acc8a34828 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/TypeDefinition.java @@ -0,0 +1,17 @@ +/* + * 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.controller.yang.model.api; + +public interface TypeDefinition> extends SchemaNode { + + T getBaseType(); + + String getUnits(); + + Object getDefaultValue(); +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/UsesNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/UsesNode.java new file mode 100644 index 0000000000..61a6d69d60 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/UsesNode.java @@ -0,0 +1,13 @@ +/* + * 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.controller.yang.model.api; + +public interface UsesNode { + SchemaPath getGroupingPath(); + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/package-info.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/package-info.java new file mode 100644 index 0000000000..77bcd9532f --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/package-info.java @@ -0,0 +1,312 @@ +/* + * 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 + */ + +/** + * Definition of structures and DOM Like API of processed YANG schema + * + *

    YANG Statement mapping

    + * + *
    + *
    anyxml + *
    {@link org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode} + * + *
    argument + *
    {@link org.opendaylight.controller.yang.model.api.ExtensionDefinition#getArgumentName()} + * + * + *
    augment + *
    {@link org.opendaylight.controller.yang.model.api.AugmentationSchema} + * + *
    base + *
    {@link org.opendaylight.controller.model.api.type.IdentityrefTypeDefinition#getIdentity()} + * + *
    belongs-to + *
    + * + *
    bit + *
    {@link org.opendaylight.controller.model.api.type.BitsTypeDefinition.Bit} + *
    {@link org.opendaylight.controller.model.api.type.BitsTypeDefinition#getBits()} + * + *
    case + *
    {@link org.opendaylight.controller.yang.model.api.ChoiceCaseNode} + * + *
    choice + *
    {@link org.opendaylight.controller.yang.model.api.ChoiceNode} + * + *
    config + *
    {@link org.opendaylight.controller.yang.model.api.DataSchemaNode#isConfiguration()} + * + *
    contact + *
    {@link org.opendaylight.controller.yang.model.api.Module#getContact()} + * + *
    container + *
    {@link org.opendaylight.controller.yang.model.api.ContainerSchemaNode} + * + *
    default + *
    + * + *
    description + *
    {@link org.opendaylight.controller.yang.model.api.SchemaNode#getDescription()} + *
    {@link org.opendaylight.controller.yang.model.api.ConstraintMetaDefinition#getDescription()} + * + *
    enum + *
    {@link org.opendaylight.controller.model.api.type.EnumTypeDefinition.EnumPair} + *
    {@link org.opendaylight.controller.model.api.type.EnumTypeDefinition#getValues()} + * + *
    error-app-tag + *
    {@link org.opendaylight.controller.yang.model.api.ConstraintMetaDefinition#getErrorAppTag()} + * + *
    error-message + *
    {@link org.opendaylight.controller.yang.model.api.ConstraintMetaDefinition#getErrorMessage()} + * + *
    extension + *
    {@link org.opendaylight.controller.yang.model.api.ExtensionDefinition} + * + *
    deviation + *
    {@link org.opendaylight.controller.yang.model.api.Deviation} + * + *
    deviate + *
    + * + *
    feature + *
    {@link org.opendaylight.controller.yang.model.api.FeatureDefinition} + * + *
    fraction-digits + *
    {@link org.opendaylight.controller.model.api.type.DecimalTypeDefinition#getFractionDigits()} + * + *
    grouping + *
    {@link org.opendaylight.controller.yang.model.api.GroupingDefinition} + * + *
    identity + *
    + * + *
    if-feature + *
    + * + *
    import + *
    {@link org.opendaylight.controller.yang.model.api.ModuleImport} + * + *
    include + *
    + * + *
    input + *
    {@link org.opendaylight.controller.yang.model.api.RpcDefinition#getInput()} + * + *
    key + *
    {@link org.opendaylight.controller.yang.model.api.ListSchemaNode#getKeyDefinition()} + * + *
    leaf + *
    {@link org.opendaylight.controller.yang.model.api.LeafSchemaNode} + * + *
    leaf-list + *
    {@link org.opendaylight.controller.yang.model.api.LeafListSchemaNode} + * + *
    length + *
    {@link org.opendaylight.controller.model.api.type.LengthConstraint} + *
    {@link org.opendaylight.controller.model.api.type.StringTypeDefinition#getLengthStatements()} + * + *
    list + *
    {@link org.opendaylight.controller.yang.model.api.ListSchemaNode} + * + *
    mandatory + *
    {@link org.opendaylight.controller.yang.model.api.ConstraintDefinition#isMandatory()} + * + *
    max-elements + *
    {@link org.opendaylight.controller.yang.model.api.ConstraintDefinition#getMinElements()} + * + *
    min-elements + *
    {@link org.opendaylight.controller.yang.model.api.ConstraintDefinition#getMaxElements()} + * + *
    module + *
    {@link org.opendaylight.controller.yang.model.api.Module} + * + *
    must + *
    {@link org.opendaylight.controller.yang.model.api.ConstraintDefinition#getMustConstraints()} + *
    {@link org.opendaylight.controller.yang.model.api.MustDefinition} + * + *
    namespace + *
    {@link org.opendaylight.controller.yang.model.api.Module#getNamespace()} + * + *
    notification + *
    {@link org.opendaylight.controller.yang.model.api.NotificationDefinition} + * + *
    ordered-by + *
    {@link org.opendaylight.controller.yang.model.api.ListSchemaNode#isUserOrdered()} + *
    {@link org.opendaylight.controller.yang.model.api.LeafListSchemaNode#isUserOrdered()} + * + *
    organization + *
    {@link org.opendaylight.controller.yang.model.api.Module#getOrganization()} + * + *
    output + *
    {@link org.opendaylight.controller.yang.model.api.RpcDefinition#getOutput()} + * + *
    path + *
    {@link org.opendaylight.controller.model.api.type.LeafrefTypeDefinition#getPathStatement()} + * + *
    pattern + *
    {@link org.opendaylight.controller.yang.model.base.type.api.PatternConstraint} + *
    {@link org.opendaylight.controller.model.api.type.StringTypeDefinition} + * + *
    position + *
    {@link org.opendaylight.controller.model.api.type.BitsTypeDefinition.Bit#getPosition()} + * + *
    prefix + *
    {@link org.opendaylight.controller.yang.model.api.Module#getPrefix()} + *
    {@link org.opendaylight.controller.yang.model.api.ModuleImport#getPrefix()} + * + *
    presence + *
    {@link org.opendaylight.controller.yang.model.api.ContainerSchemaNode#isPresenceContainer()} + * + *
    range + *
    {@link org.opendaylight.controller.model.api.type.RangeConstraint} + *
    {@link org.opendaylight.controller.model.api.type.IntegerTypeDefinition#getRangeStatements()} + *
    {@link org.opendaylight.controller.model.api.type.UnsignedIntegerTypeDefinition#getRangeStatements()} + * + *
    reference + *
    {@link org.opendaylight.controller.yang.model.api.SchemaNode#getReference()} + * + *
    refine + *
    + * + *
    require-instance + *
    {@link org.opendaylight.controller.model.api.type.InstanceIdentifierTypeDefinition#requireInstance()} + * + *
    revision + *
    {@link org.opendaylight.controller.yang.model.api.Module#getRevision()} + * + *
    revision-date + *
    {@link org.opendaylight.controller.yang.model.api.ModuleImport#getRevision()} + * + *
    rpc + *
    {@link org.opendaylight.controller.yang.model.api.RpcDefinition} + * + *
    status + *
    {@link org.opendaylight.controller.yang.model.api.SchemaNode#getStatus()} + * + *
    submodule + *
    + * + *
    type + *
    {@link org.opendaylight.controller.yang.model.api.TypeDefinition} + *
    {@link org.opendaylight.controller.yang.model.api.LeafSchemaNode#getType()} + *
    {@link org.opendaylight.controller.yang.model.api.LeafListSchemaNode#getType()} + * + *
    typedef + *
    {@link org.opendaylight.controller.yang.model.api.TypeDefinition} + * + *
    unique + *
    + * + *
    units + *
    {@link org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits()} + * + *
    uses + *
    {@link org.opendaylight.controller.yang.model.api.UsesNode} + *
    {@link org.opendaylight.controller.yang.model.api.DataNodeContainere#getUses()} + * + *
    value + *
    {@link org.opendaylight.controller.model.api.type.EnumTypeDefinition.EnumPair#getValue()} + * + *
    when + *
    {@link org.opendaylight.controller.yang.model.api.ConstraintDefinition#getWhenCondition()} + * + *
    yang-version + * + *
    yin-element + *
    + * + * + * + * + *
    add + *
    + * + *
    current + *
    + * + *
    delete + *
    + * + *
    deprecated + *
    + * + *
    false + *
    + * + *
    max + *
    + * + *
    min + *
    + * + *
    not-supported + *
    + * + *
    obsolete + *
    + * + *
    replace + *
    + * + *
    system + *
    + * + *
    true + *
    + * + *
    unbounded + *
    + * + *
    user + *
    + *
    + * + * + *

    YANG Base Type Mapping

    + * + * + *
    + *
    Integer built-in type + *
    {@link org.opendaylight.controller.model.api.type.IntegerTypeDefinition} + * + *
    Unsigned integer built-in type + *
    {@link org.opendaylight.controller.model.api.type.UnsignedIntegerTypeDefinition} + * + *
    Decimal64 built-ib type + *
    {@link org.opendaylight.controller.model.api.type.DecimalTypeDefinition} + * + *
    Boolean built-in type + *
    {@link org.opendaylight.controller.model.api.type.BooleanTypeDefinition} + * + *
    Enumeration built-in type + *
    {@link org.opendaylight.controller.model.api.type.EnumTypeDefinition} + * + *
    Bits Built-In Type + *
    {@link org.opendaylight.controller.model.api.type.BitsTypeDefinition} + * + *
    The binary Built-In Type + *
    {@link org.opendaylight.controller.model.api.type.BinaryTypeDefinition} + * + *
    The leafref Built-In Type + *
    {@link org.opendaylight.controller.model.api.type.LeafrefTypeDefinition} + * + *
    The identityref Built-In Type + *
    {@link org.opendaylight.controller.model.api.type.IdentityrefTypeDefinition} + * + *
    The empty Built-In Type + *
    {@link org.opendaylight.controller.model.api.type.EmptyTypeDefinition} + * + *
    The union Built-In Type + *
    {@link org.opendaylight.controller.model.api.type.UnionTypeDefinition} + *
    The instance-identifier Built-In Type + *
    {@link org.opendaylight.controller.model.api.type.InstanceIdentifierTypeDefinition} + * + *
    + */ +package org.opendaylight.controller.yang.model.api; + diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/pom.xml b/opendaylight/sal/yang-prototype/yang/yang-model-util/pom.xml new file mode 100644 index 0000000000..47a14e12ff --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/pom.xml @@ -0,0 +1,16 @@ + + 4.0.0 + + org.opendaylight.controller + yang + 1.0 + + yang-model-util + + + org.opendaylight.controller + yang-model-api + 1.0 + + + diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/AbstractInteger.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/AbstractInteger.java new file mode 100644 index 0000000000..58040225c1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/AbstractInteger.java @@ -0,0 +1,210 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public abstract class AbstractInteger implements IntegerTypeDefinition { + + private final QName name; + private final SchemaPath path; + + private final String description; + private final String reference; + + private String units = ""; + private final List rangeStatements; + + public AbstractInteger(final QName name, final String description, + final String reference) { + super(); + this.name = name; + this.description = description; + this.reference = reference; + this.path = BaseTypes.schemaPath(name); + + final List emptyContstraints = Collections + .emptyList(); + this.rangeStatements = Collections.unmodifiableList(emptyContstraints); + } + + public AbstractInteger(QName name, String description, String reference, + List rangeStatements) { + super(); + this.name = name; + this.description = description; + this.reference = reference; + this.rangeStatements = rangeStatements; + this.path = BaseTypes.schemaPath(name); + } + + public AbstractInteger(QName name, String description, String reference, + String units) { + super(); + this.name = name; + this.description = description; + this.reference = reference; + this.units = units; + this.path = BaseTypes.schemaPath(name); + + final List emptyContstraints = Collections + .emptyList(); + this.rangeStatements = Collections.unmodifiableList(emptyContstraints); + } + + public AbstractInteger(QName name, String description, String reference, + String units, List rangeStatements) { + super(); + this.name = name; + this.description = description; + this.reference = reference; + this.units = units; + this.rangeStatements = rangeStatements; + this.path = BaseTypes.schemaPath(name); + } + + @Override + public String getUnits() { + return units; + } + + @Override + public QName getQName() { + return name; + } + + @Override + public SchemaPath getPath() { + return path; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getReference() { + return reference; + } + + @Override + public Status getStatus() { + return Status.CURRENT; + } + + @Override + public List getRangeStatements() { + return rangeStatements; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + 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 + + ((rangeStatements == null) ? 0 : rangeStatements.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + AbstractInteger other = (AbstractInteger) obj; + if (description == null) { + if (other.description != null) { + return false; + } + } 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; + } + } else if (!path.equals(other.path)) { + return false; + } + if (rangeStatements == null) { + if (other.rangeStatements != null) { + return false; + } + } else if (!rangeStatements.equals(other.rangeStatements)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("AbstractInteger [name="); + builder.append(name); + builder.append(", path="); + builder.append(path); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", units="); + builder.append(units); + builder.append(", rangeStatements="); + builder.append(rangeStatements); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BaseConstraints.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BaseConstraints.java new file mode 100644 index 0000000000..881a3e8640 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BaseConstraints.java @@ -0,0 +1,451 @@ +/* + * 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.controller.model.util; + +import org.opendaylight.controller.model.api.type.LengthConstraint; +import org.opendaylight.controller.model.api.type.PatternConstraint; +import org.opendaylight.controller.model.api.type.RangeConstraint; + +public final class BaseConstraints { + + private BaseConstraints() { + } + + public static LengthConstraint lengthConstraint(final long min, + final long max, final String description, final String reference) { + return new LengthConstraintImpl(min, max, description, reference); + } + + public static RangeConstraint rangeConstraint(final long min, + final long max, final String description, final String reference) { + return new RangeConstraintImpl(min, max, description, reference); + } + + public static PatternConstraint patternConstraint(final String pattern, + final String description, final String reference) { + return new PatternConstraintImpl(pattern, description, reference); + } + + private static final class LengthConstraintImpl implements LengthConstraint { + + private final long min; + private final long max; + + private final String description; + private final String reference; + + private final String errorAppTag; + private final String errorMessage; + + public LengthConstraintImpl(long min, long 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 Long getMin() { + return min; + } + + @Override + public Long 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 + (int) (max ^ (max >>> 32)); + result = prime * result + (int) (min ^ (min >>> 32)); + 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(); + } + } + + private final static class RangeConstraintImpl implements RangeConstraint { + private final Long min; + private final Long max; + + private final String description; + private final String reference; + + private final String errorAppTag; + private final String errorMessage; + + public RangeConstraintImpl(Long min, Long 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 Long getMin() { + return min; + } + + @Override + public Long 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(); + } + } + + private final static 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(); + } + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BaseTypes.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BaseTypes.java new file mode 100644 index 0000000000..e02173c5de --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BaseTypes.java @@ -0,0 +1,34 @@ +/* + * 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.controller.model.util; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.SchemaPath; + +public final class BaseTypes { + + private BaseTypes() { + } + + public static final URI BaseTypesNamespace = URI + .create("urn:ietf:params:xml:ns:yang:1"); + + public static final QName constructQName(final String typeName) { + return new QName(BaseTypesNamespace, typeName); + } + + public static final SchemaPath schemaPath(final QName typeName) { + final List pathList = new ArrayList(); + pathList.add(typeName); + return new SchemaPath(pathList, true); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BinaryType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BinaryType.java new file mode 100644 index 0000000000..99a948960b --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BinaryType.java @@ -0,0 +1,247 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.BinaryTypeDefinition; +import org.opendaylight.controller.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class BinaryType implements BinaryTypeDefinition { + + private final QName name = BaseTypes.constructQName("binary"); + private final SchemaPath path = BaseTypes.schemaPath(name); + private final String description = ""; + private final String reference = ""; + + private List bytes; + private final LengthConstraint lengthConstraint; + private String units = ""; + + public BinaryType() { + super(); + + lengthConstraint = BaseConstraints.lengthConstraint(0L, Long.MAX_VALUE, + null, null); + bytes = Collections.emptyList(); + bytes = Collections.unmodifiableList(bytes); + } + + public BinaryType(final List bytes, + final LengthConstraint lengthConstraint, final String units) { + super(); + this.bytes = bytes; + this.lengthConstraint = lengthConstraint; + this.units = units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public BinaryTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return bytes; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.base.type.api.BinaryTypeDefinition#getLengthConstraint + * () + */ + @Override + public LengthConstraint getLengthConstraint() { + return lengthConstraint; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bytes == null) ? 0 : bytes.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime + * result + + ((lengthConstraint == null) ? 0 : lengthConstraint.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + BinaryType other = (BinaryType) obj; + if (bytes == null) { + if (other.bytes != null) { + return false; + } + } else if (!bytes.equals(other.bytes)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (lengthConstraint == null) { + if (other.lengthConstraint != null) { + return false; + } + } else if (!lengthConstraint.equals(other.lengthConstraint)) { + 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; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("BinaryType [name="); + builder.append(name); + builder.append(", path="); + builder.append(path); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", bytes="); + builder.append(bytes); + builder.append(", lengthConstraint="); + builder.append(lengthConstraint); + builder.append(", units="); + builder.append(units); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BitsType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BitsType.java new file mode 100644 index 0000000000..57deb07ba1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BitsType.java @@ -0,0 +1,239 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.BitsTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class BitsType implements BitsTypeDefinition { + + private final QName name = BaseTypes.constructQName("bits"); + private final SchemaPath path = BaseTypes.schemaPath(name); + private final String description = ""; + private final String reference = ""; + + private final List bits; + private String units = ""; + + /** + * Default constructor.
    + * Instantiates Bits type as empty bits list. + * + */ + public BitsType() { + super(); + bits = Collections.emptyList(); + } + + /** + * Overloaded constructor with explicit definition of bits assigned to + * BitsType. + * + * @param bits + * The bits assigned for Bits Type + */ + public BitsType(final List bits) { + super(); + this.bits = Collections.unmodifiableList(bits); + this.units = ""; + } + + public BitsType(List bits, String units) { + super(); + this.bits = Collections.unmodifiableList(bits); + ; + this.units = units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public BitsTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return bits; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + @Override + public List getBits() { + return bits; + } + + @Override + public int hashCode() { + final int prime = 31; + 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 + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + BitsType other = (BitsType) obj; + if (bits == null) { + if (other.bits != null) { + return false; + } + } else if (!bits.equals(other.bits)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } 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; + } + } else if (!path.equals(other.path)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("BitsType [name="); + builder.append(name); + builder.append(", path="); + builder.append(path); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", bits="); + builder.append(bits); + builder.append(", units="); + builder.append(units); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BooleanType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BooleanType.java new file mode 100644 index 0000000000..361ef56bbd --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/BooleanType.java @@ -0,0 +1,235 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.BooleanTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class BooleanType implements BooleanTypeDefinition { + + private final QName name = BaseTypes.constructQName("boolean"); + private final SchemaPath path = BaseTypes.schemaPath(name); + private final String description = ""; + private final String reference = ""; + + private final Boolean defaultValue; + private String units = ""; + + /** + * Default constructor with default value set to "false". + */ + public BooleanType() { + super(); + defaultValue = false; + } + + /** + * + * + * @param defaultValue + */ + public BooleanType(final Boolean defaultValue) { + super(); + this.defaultValue = defaultValue; + } + + /** + * + * + * @param defaultValue + * @param units + */ + public BooleanType(final Boolean defaultValue, final String units) { + super(); + this.defaultValue = defaultValue; + this.units = units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public BooleanTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.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 + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + BooleanType other = (BooleanType) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } 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; + } + } else if (!path.equals(other.path)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("BooleanType [name="); + builder.append(name); + builder.append(", path="); + builder.append(path); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", defaultValue="); + builder.append(defaultValue); + builder.append(", units="); + builder.append(units); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Decimal64.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Decimal64.java new file mode 100644 index 0000000000..5c6eac1cc2 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Decimal64.java @@ -0,0 +1,125 @@ +/* + * 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.controller.model.util; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.DecimalTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class Decimal64 implements DecimalTypeDefinition { + + private final QName name = BaseTypes.constructQName("decimal64"); + private final SchemaPath path; + private String units = ""; + private BigDecimal defaultValue = null; + + private final String description = "The decimal64 type represents a subset of the real numbers, which can " + + "be represented by decimal numerals. The value space of decimal64 is the set of numbers that can " + + "be obtained by multiplying a 64-bit signed integer by a negative power of ten, i.e., expressible as " + + "'i x 10^-n' where i is an integer64 and n is an integer between 1 and 18, inclusively."; + + private final String reference = "https://tools.ietf.org/html/rfc6020#section-9.3"; + + private final List rangeStatements; + private final Integer fractionDigits; + + public Decimal64(final Integer fractionDigits) { + super(); + this.fractionDigits = fractionDigits; + rangeStatements = new ArrayList(); + this.path = BaseTypes.schemaPath(name); + } + + public Decimal64(final List rangeStatements, + Integer fractionDigits) { + super(); + this.rangeStatements = rangeStatements; + this.fractionDigits = fractionDigits; + this.path = BaseTypes.schemaPath(name); + } + + public Decimal64(final String units, final BigDecimal defaultValue, + final List rangeStatements, + final Integer fractionDigits) { + super(); + this.units = units; + this.defaultValue = defaultValue; + this.rangeStatements = rangeStatements; + this.fractionDigits = fractionDigits; + this.path = BaseTypes.schemaPath(name); + } + + @Override + public DecimalTypeDefinition getBaseType() { + return this; + } + + @Override + public String getUnits() { + return units; + } + + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public QName getQName() { + return name; + } + + @Override + public SchemaPath getPath() { + return path; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getReference() { + return reference; + } + + @Override + public Status getStatus() { + return Status.CURRENT; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + @Override + public List getRangeStatements() { + return rangeStatements; + } + + @Override + public Integer getFractionDigits() { + return fractionDigits; + } + + @Override + public String toString() { + return Decimal64.class.getSimpleName() + "[qname=" + name + + ", fractionDigits=" + fractionDigits + "]"; + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/EnumerationType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/EnumerationType.java new file mode 100644 index 0000000000..34d7459b36 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/EnumerationType.java @@ -0,0 +1,241 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.EnumTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class EnumerationType implements EnumTypeDefinition { + + private final QName name = BaseTypes.constructQName("enumeration"); + private final SchemaPath path = BaseTypes.schemaPath(name); + private final String description = "The enumeration built-in type represents values from a set of assigned names."; + private final String reference = "https://tools.ietf.org/html/rfc6020#section-9.6"; + + private final List defaultEnum; + private final List enums; + private String units = ""; + + public EnumerationType(final List enums) { + super(); + this.enums = enums; + + defaultEnum = Collections.emptyList(); + } + + public EnumerationType(final List defaultEnum, + final List enums, final String units) { + super(); + this.defaultEnum = defaultEnum; + this.enums = enums; + this.units = units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public EnumTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultEnum; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.base.type.api.EnumTypeDefinition#getValues() + */ + @Override + public List getValues() { + return enums; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((defaultEnum == null) ? 0 : defaultEnum.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((enums == null) ? 0 : enums.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + EnumerationType other = (EnumerationType) obj; + if (defaultEnum == null) { + if (other.defaultEnum != null) { + return false; + } + } else if (!defaultEnum.equals(other.defaultEnum)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (enums == null) { + if (other.enums != null) { + return false; + } + } else if (!enums.equals(other.enums)) { + 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; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("EnumerationType [name="); + builder.append(name); + builder.append(", path="); + builder.append(path); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", defaultEnum="); + builder.append(defaultEnum); + builder.append(", enums="); + builder.append(enums); + builder.append(", units="); + builder.append(units); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/ExtendedType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/ExtendedType.java new file mode 100644 index 0000000000..44ca80430c --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/ExtendedType.java @@ -0,0 +1,256 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public class ExtendedType implements TypeDefinition { + + private final QName typeName; + private final TypeDefinition baseType; + private final SchemaPath path; + private final String description; + private final String reference; + private final List extensions; + + private Status status; + private String units; + private Object defaultValue; + + public static class Builder { + private final QName typeName; + private final TypeDefinition baseType; + + private final SchemaPath path; + private final String description; + private final String reference; + + private List extensions = Collections.emptyList();; + private Status status = Status.CURRENT; + private String units = ""; + private Object defaultValue = null; + + public Builder(final QName typeName, TypeDefinition baseType, + final String description, final String reference) { + this.typeName = typeName; + this.baseType = baseType; + this.path = BaseTypes.schemaPath(typeName); + this.description = description; + this.reference = reference; + } + + public Builder status(Status status) { + this.status = status; + return this; + } + + public Builder units(String units) { + this.units = units; + return this; + } + + public Builder defaultValue(final Object defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public Builder extensions(final List extensions) { + this.extensions = extensions; + return this; + } + + public ExtendedType build() { + return new ExtendedType(this); + } + } + + private ExtendedType(Builder builder) { + this.typeName = builder.typeName; + this.baseType = builder.baseType; + this.path = builder.path; + this.description = builder.description; + this.reference = builder.reference; + this.extensions = builder.extensions; + this.status = builder.status; + this.units = builder.units; + this.defaultValue = builder.defaultValue; + } + + @Override + public TypeDefinition getBaseType() { + return baseType; + } + + @Override + public String getUnits() { + return units; + } + + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public QName getQName() { + return typeName; + } + + @Override + public SchemaPath getPath() { + return path; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getReference() { + return reference; + } + + @Override + public Status getStatus() { + return status; + } + + @Override + public List getExtensionSchemaNodes() { + return extensions; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((baseType == null) ? 0 : baseType.hashCode()); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + + ((extensions == null) ? 0 : extensions.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + + ((typeName == null) ? 0 : typeName.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ExtendedType other = (ExtendedType) obj; + if (baseType == null) { + if (other.baseType != null) { + return false; + } + } else if (!baseType.equals(other.baseType)) { + return false; + } + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (extensions == null) { + if (other.extensions != null) { + return false; + } + } else if (!extensions.equals(other.extensions)) { + return false; + } + if (path == null) { + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (status != other.status) { + return false; + } + if (typeName == null) { + if (other.typeName != null) { + return false; + } + } else if (!typeName.equals(other.typeName)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder2 = new StringBuilder(); + builder2.append("ExtendedType [typeName="); + builder2.append(typeName); + builder2.append(", baseType="); + builder2.append(baseType); + builder2.append(", path="); + builder2.append(path); + builder2.append(", description="); + builder2.append(description); + builder2.append(", reference="); + builder2.append(reference); + builder2.append(", extensions="); + builder2.append(extensions); + builder2.append(", status="); + builder2.append(status); + builder2.append(", units="); + builder2.append(units); + builder2.append(", defaultValue="); + builder2.append(defaultValue); + builder2.append("]"); + return builder2.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/IdentityType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/IdentityType.java new file mode 100644 index 0000000000..2c102060e3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/IdentityType.java @@ -0,0 +1,223 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.IdentityTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class IdentityType implements IdentityTypeDefinition { + + private final QName name = BaseTypes.constructQName("identity"); + private final SchemaPath path = BaseTypes.schemaPath(name); + private final String description = ""; + private final String reference = ""; + + private String units = ""; + private final QName identityName; + + public IdentityType(QName identityName) { + super(); + this.identityName = identityName; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IdentityTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.base.type.api.IdentityTypeDefinition#getIdentityName + * () + */ + @Override + public QName getIdentityName() { + return identityName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + + ((identityName == null) ? 0 : identityName.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + IdentityType other = (IdentityType) obj; + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (identityName == null) { + if (other.identityName != null) { + return false; + } + } else if (!identityName.equals(other.identityName)) { + 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; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("IdentityType [name="); + builder.append(name); + builder.append(", path="); + builder.append(path); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", units="); + builder.append(units); + builder.append(", identityName="); + builder.append(identityName); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Identityref.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Identityref.java new file mode 100644 index 0000000000..c4040c1f23 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Identityref.java @@ -0,0 +1,224 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.IdentityTypeDefinition; +import org.opendaylight.controller.model.api.type.IdentityrefTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class Identityref implements IdentityrefTypeDefinition { + + private final QName name = BaseTypes.constructQName("identityref"); + private final SchemaPath path = BaseTypes.schemaPath(name); + private final String description = ""; + private final String reference = ""; + + private final IdentityTypeDefinition identity; + + private String units = ""; + + public Identityref(IdentityTypeDefinition identity) { + super(); + this.identity = identity; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IdentityTypeDefinition getBaseType() { + return identity; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return identity; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.base.type.api.IdentityrefTypeDefinition#getIdentityName + * () + */ + @Override + public IdentityTypeDefinition getIdentity() { + return identity; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + + ((identity == null) ? 0 : identity.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Identityref other = (Identityref) obj; + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (identity == null) { + if (other.identity != null) { + return false; + } + } else if (!identity.equals(other.identity)) { + 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; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("IdentityrefType [name="); + builder.append(name); + builder.append(", path="); + builder.append(path); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", identity="); + builder.append(identity); + builder.append(", units="); + builder.append(units); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/InstanceIdentifier.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/InstanceIdentifier.java new file mode 100644 index 0000000000..8376d9bd62 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/InstanceIdentifier.java @@ -0,0 +1,151 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.InstanceIdentifierTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class InstanceIdentifier implements InstanceIdentifierTypeDefinition { + + private static final QName name = BaseTypes + .constructQName("instance-identifier"); + private static final String description = ""; + private static final String reference = ""; + + private final transient SchemaPath path = BaseTypes.schemaPath(name); + private final RevisionAwareXPath xpath; + private final String units = ""; + + private final boolean requireInstance; + + public InstanceIdentifier(RevisionAwareXPath xpath, boolean requireInstance) { + super(); + this.xpath = xpath; + this.requireInstance = requireInstance; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public InstanceIdentifierTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return xpath; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getExtensionSchemaNodes() + */ + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.type.InstanceIdentifierTypeDefinition# + * getPathStatement() + */ + @Override + public RevisionAwareXPath getPathStatement() { + return xpath; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.type.InstanceIdentifierTypeDefinition# + * requireInstance() + */ + @Override + public boolean requireInstance() { + return requireInstance; + } + +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int16.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int16.java new file mode 100644 index 0000000000..49ac4d1649 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int16.java @@ -0,0 +1,100 @@ +/* + * 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.controller.model.util; + +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; + +public class Int16 extends AbstractInteger { + + private static final QName name = BaseTypes.constructQName("int16"); + private Short defaultValue = null; + private static final String description = ""; + private static final String reference = ""; + + public Int16() { + super(name, description, reference); + } + + public Int16(final Short defaultValue) { + super(name, description, reference); + this.defaultValue = defaultValue; + } + + public Int16(final List rangeStatements, + final Short defaultValue) { + super(name, description, reference, rangeStatements); + this.defaultValue = defaultValue; + } + + public Int16(final String units, final Short defaultValue) { + super(name, description, reference, units); + this.defaultValue = defaultValue; + } + + public Int16(final List rangeStatements, + final String units, final Short defaultValue) { + super(name, description, reference, units, rangeStatements); + this.defaultValue = defaultValue; + } + + @Override + public IntegerTypeDefinition getBaseType() { + return this; + } + + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Int16 other = (Int16) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Int16 [defaultValue="); + builder.append(defaultValue); + builder.append(", AbstractInteger="); + builder.append(super.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int32.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int32.java new file mode 100644 index 0000000000..18908750c4 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int32.java @@ -0,0 +1,110 @@ +/* + * 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.controller.model.util; + +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; + +public class Int32 extends AbstractInteger { + + private static final QName name = BaseTypes.constructQName("int32"); + private Integer defaultValue = null; + private static final String description = ""; + private static final String reference = ""; + + public Int32() { + super(name, description, reference); + } + + public Int32(final Integer defaultValue) { + super(name, description, reference); + this.defaultValue = defaultValue; + } + + public Int32(final List rangeStatements, + final Integer defaultValue) { + super(name, description, reference, rangeStatements); + this.defaultValue = defaultValue; + } + + public Int32(final String units, final Integer defaultValue) { + super(name, description, reference, units); + this.defaultValue = defaultValue; + } + + public Int32(final List rangeStatements, + final String units, final Integer defaultValue) { + super(name, description, reference, units, rangeStatements); + this.defaultValue = defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IntegerTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Int32 other = (Int32) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Int32 [defaultValue="); + builder.append(defaultValue); + builder.append(", AbstractInteger="); + builder.append(super.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int64.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int64.java new file mode 100644 index 0000000000..c03c6b7bf6 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int64.java @@ -0,0 +1,110 @@ +/* + * 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.controller.model.util; + +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; + +public class Int64 extends AbstractInteger { + + private static final QName name = BaseTypes.constructQName("int64"); + private Long defaultValue = null; + private static final String description = ""; + private static final String reference = ""; + + public Int64() { + super(name, description, reference); + } + + public Int64(final Long defaultValue) { + super(name, description, reference); + this.defaultValue = defaultValue; + } + + public Int64(final List rangeStatements, + final Long defaultValue) { + super(name, description, reference, rangeStatements); + this.defaultValue = defaultValue; + } + + public Int64(final String units, final Long defaultValue) { + super(name, description, reference, units); + this.defaultValue = defaultValue; + } + + public Int64(final List rangeStatements, + final String units, final Long defaultValue) { + super(name, description, reference, units, rangeStatements); + this.defaultValue = defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IntegerTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Int64 other = (Int64) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Int64 [defaultValue="); + builder.append(defaultValue); + builder.append(", AbstractInteger="); + builder.append(super.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int8.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int8.java new file mode 100644 index 0000000000..ebb5fa7c6a --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Int8.java @@ -0,0 +1,110 @@ +/* + * 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.controller.model.util; + +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; + +public class Int8 extends AbstractInteger { + + private static final QName name = BaseTypes.constructQName("int8"); + private Byte defaultValue = null; + private static final String description = ""; + private static final String reference = ""; + + public Int8() { + super(name, description, reference); + } + + public Int8(final Byte defaultValue) { + super(name, description, reference); + this.defaultValue = defaultValue; + } + + public Int8(final List rangeStatements, + final Byte defaultValue) { + super(name, description, reference, rangeStatements); + this.defaultValue = defaultValue; + } + + public Int8(final String units, final Byte defaultValue) { + super(name, description, reference, units); + this.defaultValue = defaultValue; + } + + public Int8(final List rangeStatements, + final String units, final Byte defaultValue) { + super(name, description, reference, units, rangeStatements); + this.defaultValue = defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IntegerTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Int8 other = (Int8) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Int8 [defaultValue="); + builder.append(defaultValue); + builder.append(", AbstractInteger="); + builder.append(super.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Leafref.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Leafref.java new file mode 100644 index 0000000000..53c2c82ac3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Leafref.java @@ -0,0 +1,192 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.LeafrefTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class Leafref implements LeafrefTypeDefinition { + private static final QName name = BaseTypes.constructQName("leafref"); + private static final String description = ""; + private static final String reference = ""; + private final SchemaPath path = BaseTypes.schemaPath(name); + private final RevisionAwareXPath xpath; + private final String units = ""; + + public Leafref(RevisionAwareXPath xpath) { + super(); + this.xpath = xpath; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public LeafrefTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getExtensionSchemaNodes() + */ + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition#getPathStatement() + */ + @Override + public RevisionAwareXPath getPathStatement() { + return xpath; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + result = prime * result + ((xpath == null) ? 0 : xpath.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Leafref other = (Leafref) obj; + if (path == null) { + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + if (xpath == null) { + if (other.xpath != null) { + return false; + } + } else if (!xpath.equals(other.xpath)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Leafref [path="); + builder.append(path); + builder.append(", xpath="); + builder.append(xpath); + builder.append(", units="); + builder.append(units); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/StringType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/StringType.java new file mode 100644 index 0000000000..f640831297 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/StringType.java @@ -0,0 +1,282 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.LengthConstraint; +import org.opendaylight.controller.model.api.type.PatternConstraint; +import org.opendaylight.controller.model.api.type.StringTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class StringType implements StringTypeDefinition { + + private final QName name = BaseTypes.constructQName("string");; + private final SchemaPath path; + private String defaultValue = ""; + private final String description = ""; + private final String reference = ""; + private final List lengthStatements; + private final List patterns; + private String units = ""; + + public StringType() { + super(); + path = BaseTypes.schemaPath(name); + this.lengthStatements = Collections.emptyList(); + this.patterns = Collections.emptyList(); + } + + public StringType(List lengthStatements, + List patterns) { + super(); + path = BaseTypes.schemaPath(name); + this.lengthStatements = Collections.unmodifiableList(lengthStatements); + this.patterns = Collections.unmodifiableList(patterns); + } + + public StringType(final String defaultValue, + final List lengthStatements, + final List patterns, final String units) { + super(); + path = BaseTypes.schemaPath(name); + this.defaultValue = defaultValue; + this.lengthStatements = lengthStatements; + this.patterns = patterns; + this.units = units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public StringTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return Status.CURRENT; + } + + /* + * (non-Javadoc) + * + * @see + * com.csico.yang.model.base.type.api.StringTypeDefinition#getLengthStatements + * () + */ + @Override + public List getLengthStatements() { + return lengthStatements; + } + + /* + * (non-Javadoc) + * + * @see + * com.csico.yang.model.base.type.api.StringTypeDefinition#getPatterns() + */ + @Override + public List getPatterns() { + return patterns; + } + + @Override + public List getExtensionSchemaNodes() { + return Collections.emptyList(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + 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 + + ((patterns == null) ? 0 : patterns.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + StringType other = (StringType) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (lengthStatements == null) { + if (other.lengthStatements != null) { + return false; + } + } 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 != null) && (other.path != null)) { + if (!path.getPath().equals(other.path.getPath())) { + return false; + } + } + if (patterns == null) { + if (other.patterns != null) { + return false; + } + } else if (!patterns.equals(other.patterns)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("StringType [name="); + builder.append(name); + builder.append(", path="); + builder.append(path); + builder.append(", defaultValue="); + builder.append(defaultValue); + builder.append(", description="); + builder.append(description); + builder.append(", reference="); + builder.append(reference); + builder.append(", lengthStatements="); + builder.append(lengthStatements); + builder.append(", patterns="); + builder.append(patterns); + builder.append(", units="); + builder.append(units); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint16.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint16.java new file mode 100644 index 0000000000..5094d77bd5 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint16.java @@ -0,0 +1,104 @@ +/* + * 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.controller.model.util; + +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; + +public class Uint16 extends AbstractInteger { + + private static final QName name = BaseTypes.constructQName("uint16"); + private Integer defaultValue = null; + private static final String description = ""; + private static final String reference = ""; + + public Uint16() { + super(name, description, reference); + } + + public Uint16(final Integer defaultValue) { + super(name, description, reference); + this.defaultValue = defaultValue; + } + + public Uint16(final List rangeStatements, + final Integer defaultValue) { + super(name, description, reference, rangeStatements); + this.defaultValue = defaultValue; + } + + public Uint16(final String units, final Integer defaultValue) { + super(name, description, reference, units); + this.defaultValue = defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IntegerTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Uint16 other = (Uint16) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Uint16 [defaultValue="); + builder.append(defaultValue); + builder.append(", AbstractInteger="); + builder.append(super.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint32.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint32.java new file mode 100644 index 0000000000..48c6a47ecb --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint32.java @@ -0,0 +1,104 @@ +/* + * 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.controller.model.util; + +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; + +public class Uint32 extends AbstractInteger { + + private static final QName name = BaseTypes.constructQName("uint32"); + private Long defaultValue = null; + private static final String description = ""; + private static final String reference = ""; + + public Uint32() { + super(name, description, reference); + } + + public Uint32(final Long defaultValue) { + super(name, description, reference); + this.defaultValue = defaultValue; + } + + public Uint32(final List rangeStatements, + final Long defaultValue) { + super(name, description, reference, rangeStatements); + this.defaultValue = defaultValue; + } + + public Uint32(final String units, final Long defaultValue) { + super(name, description, reference, units); + this.defaultValue = defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IntegerTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Uint32 other = (Uint32) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Uint32 [defaultValue="); + builder.append(defaultValue); + builder.append(", AbstractInteger="); + builder.append(super.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint64.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint64.java new file mode 100644 index 0000000000..8ac7c39aff --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint64.java @@ -0,0 +1,105 @@ +/* + * 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.controller.model.util; + +import java.math.BigInteger; +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; + +public class Uint64 extends AbstractInteger { + + private static final QName name = BaseTypes.constructQName("uint32"); + private BigInteger defaultValue = null; + private static final String description = ""; + private static final String reference = ""; + + public Uint64() { + super(name, description, reference); + } + + public Uint64(final BigInteger defaultValue) { + super(name, description, reference); + this.defaultValue = defaultValue; + } + + public Uint64(final List rangeStatements, + final BigInteger defaultValue) { + super(name, description, reference, rangeStatements); + this.defaultValue = defaultValue; + } + + public Uint64(final String units, final BigInteger defaultValue) { + super(name, description, reference, units); + this.defaultValue = defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IntegerTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Uint64 other = (Uint64) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Uint64 [defaultValue="); + builder.append(defaultValue); + builder.append(", AbstractInteger="); + builder.append(super.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint8.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint8.java new file mode 100644 index 0000000000..39314fe718 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/Uint8.java @@ -0,0 +1,110 @@ +/* + * 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.controller.model.util; + +import java.util.List; + +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.common.QName; + +public class Uint8 extends AbstractInteger { + + private static final QName name = BaseTypes.constructQName("uint8"); + private Short defaultValue = null; + private static final String description = ""; + private static final String reference = ""; + + public Uint8() { + super(name, description, reference); + } + + public Uint8(final Short defaultValue) { + super(name, description, reference); + this.defaultValue = defaultValue; + } + + public Uint8(final List rangeStatements, + final Short defaultValue) { + super(name, description, reference, rangeStatements); + this.defaultValue = defaultValue; + } + + public Uint8(final String units, final Short defaultValue) { + super(name, description, reference, units); + this.defaultValue = defaultValue; + } + + public Uint8(final List rangeStatements, + final String units, final Short defaultValue) { + super(name, description, reference, units, rangeStatements); + this.defaultValue = defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public IntegerTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue() + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Uint8 other = (Uint8) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Uint8 [defaultValue="); + builder.append(defaultValue); + builder.append(", AbstractInteger="); + builder.append(super.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/UnknownType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/UnknownType.java new file mode 100644 index 0000000000..b1e1082c60 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/UnknownType.java @@ -0,0 +1,440 @@ +/* + * 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.controller.model.util; + +import java.util.Collections; +import java.util.List; + +import org.opendaylight.controller.model.api.type.LengthConstraint; +import org.opendaylight.controller.model.api.type.PatternConstraint; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.model.api.type.UnknownTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; + +public class UnknownType implements UnknownTypeDefinition { + + private final QName name; + private final SchemaPath path; + private final String description; + private final String reference; + + private final List lengthStatements; + private final List patterns; + private final List rangeStatements; + private final List extensions; + private final LengthConstraint lengthConstraint; + + private final Status status; + private final String units; + private final Object defaultValue; + + public static class Builder { + + private final QName name; + private final SchemaPath path; + private String description; + private String reference; + + private List lengthStatements = Collections + .emptyList(); + private List patterns = Collections.emptyList(); + private List rangeStatements = Collections.emptyList(); + private List extensions = Collections.emptyList(); + private LengthConstraint lengthConstraint = null; + + private Status status = Status.CURRENT; + private String units = ""; + private Object defaultValue = null; + + public Builder(final QName name, final String description, + final String reference) { + this.name = name; + this.path = BaseTypes.schemaPath(name); + this.description = description; + this.reference = reference; + } + + public Builder(final QName name) { + this.name = name; + this.path = BaseTypes.schemaPath(name); + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder reference(String reference) { + this.reference = reference; + return this; + } + + public Builder lengthStatements( + final List lengthStatements) { + this.lengthStatements = lengthStatements; + return this; + } + + public Builder patterns(final List patterns) { + this.patterns = patterns; + return this; + } + + public Builder rangeStatements( + final List rangeStatements) { + this.rangeStatements = rangeStatements; + return this; + } + + public Builder extensions(final List extensions) { + this.extensions = extensions; + return this; + } + + public Builder lengthConstraint(final LengthConstraint lengthConstraint) { + this.lengthConstraint = lengthConstraint; + return this; + } + + public Builder status(Status status) { + this.status = status; + return this; + } + + public Builder units(String units) { + this.units = units; + return this; + } + + public Builder defaultValue(final Object defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public UnknownTypeDefinition build() { + return new UnknownType(this); + } + } + + private UnknownType(Builder builder) { + this.name = builder.name; + this.path = builder.path; + this.description = builder.description; + this.reference = builder.reference; + this.lengthStatements = builder.lengthStatements; + this.patterns = builder.patterns; + this.rangeStatements = builder.rangeStatements; + this.extensions = builder.extensions; + this.lengthConstraint = builder.lengthConstraint; + this.status = builder.status; + this.units = builder.units; + this.defaultValue = builder.defaultValue; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() + */ + @Override + public UnknownTypeDefinition getBaseType() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() + */ + @Override + public String getUnits() { + return units; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue + * () + */ + @Override + public Object getDefaultValue() { + return defaultValue; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() + */ + @Override + public QName getQName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() + */ + @Override + public SchemaPath getPath() { + return path; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() + */ + @Override + public String getDescription() { + return description; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() + */ + @Override + public String getReference() { + return reference; + } + + /* + * (non-Javadoc) + * + * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() + */ + @Override + public Status getStatus() { + return status; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.SchemaNode#getExtensionSchemaNodes + * () + */ + @Override + public List getExtensionSchemaNodes() { + return extensions; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.type.UnknownTypeDefinition + * #getRangeStatements() + */ + @Override + public List getRangeStatements() { + return rangeStatements; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.type.UnknownTypeDefinition + * #getLengthStatements() + */ + @Override + public List getLengthStatements() { + return lengthStatements; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.type.UnknownTypeDefinition + * #getPatterns() + */ + @Override + public List getPatterns() { + return patterns; + } + + /* + * (non-Javadoc) + * + * @see + * org.opendaylight.controller.yang.model.api.type.UnknownTypeDefinition + * #getLengthConstraint() + */ + @Override + public LengthConstraint getLengthConstraint() { + return lengthConstraint; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + + ((extensions == null) ? 0 : extensions.hashCode()); + result = prime + * result + + ((lengthConstraint == null) ? 0 : lengthConstraint.hashCode()); + 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 + + ((patterns == null) ? 0 : patterns.hashCode()); + result = prime * result + + ((rangeStatements == null) ? 0 : rangeStatements.hashCode()); + result = prime * result + + ((reference == null) ? 0 : reference.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + ((units == null) ? 0 : units.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + UnknownType other = (UnknownType) obj; + if (defaultValue == null) { + if (other.defaultValue != null) { + return false; + } + } else if (!defaultValue.equals(other.defaultValue)) { + return false; + } + if (description == null) { + if (other.description != null) { + return false; + } + } else if (!description.equals(other.description)) { + return false; + } + if (extensions == null) { + if (other.extensions != null) { + return false; + } + } else if (!extensions.equals(other.extensions)) { + return false; + } + if (lengthConstraint == null) { + if (other.lengthConstraint != null) { + return false; + } + } else if (!lengthConstraint.equals(other.lengthConstraint)) { + return false; + } + if (lengthStatements == null) { + if (other.lengthStatements != null) { + return false; + } + } 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.equals(other.path)) { + return false; + } + if (patterns == null) { + if (other.patterns != null) { + return false; + } + } else if (!patterns.equals(other.patterns)) { + return false; + } + if (rangeStatements == null) { + if (other.rangeStatements != null) { + return false; + } + } else if (!rangeStatements.equals(other.rangeStatements)) { + return false; + } + if (reference == null) { + if (other.reference != null) { + return false; + } + } else if (!reference.equals(other.reference)) { + return false; + } + if (status != other.status) { + return false; + } + if (units == null) { + if (other.units != null) { + return false; + } + } else if (!units.equals(other.units)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder2 = new StringBuilder(); + builder2.append("UnknownType [name="); + builder2.append(name); + builder2.append(", path="); + builder2.append(path); + builder2.append(", description="); + builder2.append(description); + builder2.append(", reference="); + builder2.append(reference); + builder2.append(", lengthStatements="); + builder2.append(lengthStatements); + builder2.append(", patterns="); + builder2.append(patterns); + builder2.append(", rangeStatements="); + builder2.append(rangeStatements); + builder2.append(", extensions="); + builder2.append(extensions); + builder2.append(", lengthConstraint="); + builder2.append(lengthConstraint); + builder2.append(", status="); + builder2.append(status); + builder2.append(", units="); + builder2.append(units); + builder2.append(", defaultValue="); + builder2.append(defaultValue); + builder2.append("]"); + return builder2.toString(); + } +} diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/YangTypesConverter.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/YangTypesConverter.java new file mode 100644 index 0000000000..1ab1dc63b1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/model/util/YangTypesConverter.java @@ -0,0 +1,115 @@ +/* + * 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.controller.model.util; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.model.api.type.BinaryTypeDefinition; +import org.opendaylight.controller.model.api.type.BitsTypeDefinition; +import org.opendaylight.controller.model.api.type.BooleanTypeDefinition; +import org.opendaylight.controller.model.api.type.DecimalTypeDefinition; +import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.model.api.type.RangeConstraint; +import org.opendaylight.controller.model.api.type.StringTypeDefinition; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public class YangTypesConverter { + + private static final Map>> baseYangTypeMap = new HashMap>>(); + private static final Set baseYangTypes = new HashSet(); + + private static final TypeDefinition BINARY = new BinaryType(); + private static final TypeDefinition BITS = new BitsType(); + private static final TypeDefinition BOOLEAN_TYPE = new BooleanType(); + private static final TypeDefinition INT8_TYPE = new Int8(); + private static final TypeDefinition INT16_TYPE = new Int16(); + private static final TypeDefinition INT32_TYPE = new Int32(); + private static final TypeDefinition INT64_TYPE = new Int64(); + private static final TypeDefinition STRING_TYPE = new StringType(); + private static final TypeDefinition UINT8_TYPE = new Uint8(); + private static final TypeDefinition UINT16_TYPE = new Int16(); + private static final TypeDefinition UINT32_TYPE = new Int32(); + private static final TypeDefinition UINT64_TYPE = new Int64(); + + static { + baseYangTypeMap.put("binary", BINARY); + baseYangTypeMap.put("bits", BITS); + baseYangTypeMap.put("boolean", BOOLEAN_TYPE); + baseYangTypeMap.put("int8", INT8_TYPE); + baseYangTypeMap.put("int16", INT16_TYPE); + baseYangTypeMap.put("int32", INT32_TYPE); + baseYangTypeMap.put("int64", INT64_TYPE); + baseYangTypeMap.put("string", STRING_TYPE); + baseYangTypeMap.put("uint8", UINT8_TYPE); + baseYangTypeMap.put("uint16", UINT16_TYPE); + baseYangTypeMap.put("uint32", UINT32_TYPE); + baseYangTypeMap.put("uint64", UINT64_TYPE); + + baseYangTypes.add("binary"); + baseYangTypes.add("bits"); + baseYangTypes.add("boolean"); + baseYangTypes.add("decimal64"); + baseYangTypes.add("enumeration"); + baseYangTypes.add("int8"); + baseYangTypes.add("int16"); + baseYangTypes.add("int32"); + baseYangTypes.add("int64"); + baseYangTypes.add("string"); + baseYangTypes.add("uint8"); + baseYangTypes.add("uint16"); + baseYangTypes.add("uint32"); + baseYangTypes.add("uint64"); + } + + public static boolean isBaseYangType(String type) { + return baseYangTypes.contains(type); + } + + public static TypeDefinition javaTypeForBaseYangType(QName typeQName) { + TypeDefinition type = baseYangTypeMap.get(typeQName.getLocalName()); + return type; + } + + public static TypeDefinition javaTypeForBaseYangType(String typeName) { + TypeDefinition type = baseYangTypeMap.get(typeName); + return type; + } + + public static TypeDefinition javaTypeForBaseYangIntegerType( + String typeName, List ranges) { + if (typeName.equals("int8")) { + return new Int8(ranges, null); + } else if (typeName.equals("int16")) { + return new Int16(ranges, null); + } else if (typeName.equals("int32")) { + return new Int32(ranges, null); + } else if (typeName.equals("int64")) { + return new Int64(ranges, null); + } else if (typeName.equals("uint8")) { + return new Uint8(ranges, null); + } else if (typeName.equals("uint16")) { + return new Uint16(ranges, null); + } else if (typeName.equals("uint32")) { + return new Uint32(ranges, null); + } else if (typeName.equals("uint64")) { + return new Uint64(ranges, null); + } + return null; + } + + public static TypeDefinition javaTypeForBaseYangDecimal64Type( + List rangeStatements, int fractionDigits) { + return new Decimal64(rangeStatements, fractionDigits); + } + +} diff --git a/sitebuildsettings-pom.xml b/sitebuildsettings-pom.xml new file mode 100644 index 0000000000..7b144d5238 --- /dev/null +++ b/sitebuildsettings-pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + 3.0 + + sitebuildsettings + sitebuildsettings + 1.0.0-SNAPSHOT + pom + + + https://sonar.opendaylight.org/ + http://nexus.opendaylight.org/content + dav:http://nexus.opendaylight.org/content/sites/site + thirdparty + opendaylight + + diff --git a/third-party/commons/thirdparty/pom.xml b/third-party/commons/thirdparty/pom.xml new file mode 100644 index 0000000000..28a682723a --- /dev/null +++ b/third-party/commons/thirdparty/pom.xml @@ -0,0 +1,197 @@ + + + 4.0.0 + + 3.0 + + + + sitebuildsettings + sitebuildsettings + 1.0.0-SNAPSHOT + ../../../sitebuildsettings-pom.xml + + org.opendaylight.controller + commons.thirdparty + 1.1.0-SNAPSHOT + pom + + + 3.2 + 2.6 + UTF-8 + 2.3.2 + 2.13 + + + + + central2 + central2 + ${nexusproxy}/repositories/central2/ + + + + + + fastreassembly + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.4 + + + copyfastreassembly + install + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + ${project.groupId}.${project.artifactId}-${project.version}.jar + + + ${fastreassembly.directory} + + + + + + + + + + + + + com.googlecode.maven-java-formatter-plugin + maven-java-formatter-plugin + 0.3.1 + + + **/* + + + + + + + + org.apache.maven.plugins + maven-site-plugin + ${siteplugin} + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + ${projectinfo} + + false + false + + + index + project-team + license + mailing-list + plugin-management + cim + issue-tracking + scm + summary + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.10 + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + org.jboss.apiviz.APIviz + + org.jboss.apiviz + apiviz + 1.3.2.GA + + ${project.artifactId}-${build.suffix} + true + UTF-8 + UTF-8 + UTF-8 + true + true + true + true + net.sf.jnetlib.*:cern.*:corejava + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + true + true + + + + + + + + + + + + + central2 + central2 + ${nexusproxy}/repositories/central2/ + + + + central + central + ${nexusproxy}/repositories/central/ + + + + ${thirdpartyID} + thirdparty + ${nexusproxy}/repositories/thirdparty + + + + + + ${thirdpartyID} + ${nexusproxy}/repositories/thirdparty + + + + ${thirdpartyID}-snapshot + ${nexusproxy}/repositories/thirdparty-snapshot + + + + website + ${sitedeploy} + + + diff --git a/third-party/jersey-servlet/pom.xml b/third-party/jersey-servlet/pom.xml new file mode 100644 index 0000000000..dfb8968a5e --- /dev/null +++ b/third-party/jersey-servlet/pom.xml @@ -0,0 +1,82 @@ + + + + + org.opendaylight.controller + commons.thirdparty + 1.1.0-SNAPSHOT + ../commons/thirdparty + + 4.0.0 + org.opendaylight.controller.thirdparty + com.sun.jersey.jersey-servlet + 1.17-SNAPSHOT + bundle + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + *;scope=!provided;type=!pom;inline=false + false + + com.sun.jersey.api.core.servlet, + com.sun.jersey.spi.container.servlet, + com.sun.jersey.spi.scanning.servlet, + com.sun.jersey.server.impl.container.servlet + + + com.sun.jersey.api.container, + com.sun.jersey.api.core, + com.sun.jersey.api.model, + com.sun.jersey.api.representation, + com.sun.jersey.api.uri, + com.sun.jersey.api.view, + com.sun.jersey.core.header, + com.sun.jersey.core.reflection, + com.sun.jersey.core.spi.component, + com.sun.jersey.core.spi.component.ioc, + com.sun.jersey.core.spi.scanning, + com.sun.jersey.core.util, + com.sun.jersey.server.impl, + com.sun.jersey.server.impl.application, + com.sun.jersey.server.impl.inject, + com.sun.jersey.server.impl.monitoring, + com.sun.jersey.server.probes, + com.sun.jersey.server.spi.component, + com.sun.jersey.spi, + com.sun.jersey.spi.container, + com.sun.jersey.spi.dispatch, + com.sun.jersey.spi.inject, + com.sun.jersey.spi.service, + com.sun.jersey.spi.template, + javax.naming, + javax.ws.rs, + javax.ws.rs.core, + javax.ws.rs.ext, + *;resolution:=optional + + + + + + + + + + com.sun.jersey + jersey-servlet + 1.17 + + + equinoxSDK381 + javax.servlet + 3.0.0.v201112011016 + provided + + + diff --git a/third-party/net.sf.jung2/pom.xml b/third-party/net.sf.jung2/pom.xml new file mode 100644 index 0000000000..bfe59c59ca --- /dev/null +++ b/third-party/net.sf.jung2/pom.xml @@ -0,0 +1,72 @@ + + + + + org.opendaylight.controller + commons.thirdparty + 1.1.0-SNAPSHOT + ../commons/thirdparty + + 4.0.0 + org.opendaylight.controller.thirdparty + net.sf.jung2 + 2.0.1-SNAPSHOT + bundle + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + *;scope=compile|runtime;type=!pom;inline=false + false + + org.apache.commons*, + edu.uci.ics.jung.algorithms.blockmodel, + edu.uci.ics.jung.algorithms.cluster, + edu.uci.ics.jung.algorithms.filters, + edu.uci.ics.jung.algorithms.flows, + edu.uci.ics.jung.algorithms.generators, + edu.uci.ics.jung.algorithms.generators.random, + edu.uci.ics.jung.algorithms.layout, + edu.uci.ics.jung.algorithms.layout.util, + edu.uci.ics.jung.algorithms.metrics, + edu.uci.ics.jung.algorithms.scoring, + edu.uci.ics.jung.algorithms.scoring.util, + edu.uci.ics.jung.algorithms.shortestpath, + edu.uci.ics.jung.algorithms.transformation, + edu.uci.ics.jung.algorithms.util, + edu.uci.ics.jung.graph;-split-package:=merge-first, + edu.uci.ics.jung.graph.event, + edu.uci.ics.jung.graph.util;-split-package:=merge-first + + + !* + + + + + + + + + + net.sf.jung + jung-api + 2.0.1 + + + net.sf.jung + jung-graph-impl + 2.0.1 + + + net.sourceforge.collections + collections-generic + 4.01 + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/StructurallyEquivalent.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/StructurallyEquivalent.java new file mode 100644 index 0000000000..a9d457345e --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/StructurallyEquivalent.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2004, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * Created on Jan 28, 2004 + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.blockmodel; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.CollectionUtils; +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Identifies sets of structurally equivalent vertices in a graph. Vertices + * i and j are structurally equivalent iff the set of i's + * neighbors is identical to the set of j's neighbors, with the + * exception of i and j themselves. This algorithm finds all + * sets of equivalent vertices in O(V^2) time. + * + *

    You can extend this class to have a different definition of equivalence (by + * overriding isStructurallyEquivalent), and may give it hints for + * accelerating the process by overriding canPossiblyCompare. + * (For example, in a bipartite graph, canPossiblyCompare may + * return false for vertices in + * different partitions. This function should be fast.) + * + * @author Danyel Fisher + */ +public class StructurallyEquivalent implements Transformer, VertexPartition> +{ + public VertexPartition transform(Graph g) + { + Set> vertex_pairs = getEquivalentPairs(g); + + Set> rv = new HashSet>(); + Map> intermediate = new HashMap>(); + for (Pair p : vertex_pairs) + { + Set res = intermediate.get(p.getFirst()); + if (res == null) + res = intermediate.get(p.getSecond()); + if (res == null) // we haven't seen this one before + res = new HashSet(); + res.add(p.getFirst()); + res.add(p.getSecond()); + intermediate.put(p.getFirst(), res); + intermediate.put(p.getSecond(), res); + } + rv.addAll(intermediate.values()); + + // pick up the vertices which don't appear in intermediate; they are + // singletons (equivalence classes of size 1) + Collection singletons = CollectionUtils.subtract(g.getVertices(), + intermediate.keySet()); + for (V v : singletons) + { + Set v_set = Collections.singleton(v); + intermediate.put(v, v_set); + rv.add(v_set); + } + + return new VertexPartition(g, intermediate, rv); + } + + /** + * For each vertex pair v, v1 in G, checks whether v and v1 are fully + * equivalent: meaning that they connect to the exact same vertices. (Is + * this regular equivalence, or whathaveyou?) + * + * Returns a Set of Pairs of vertices, where all the vertices in the inner + * Pairs are equivalent. + * + * @param g + */ + protected Set> getEquivalentPairs(Graph g) { + + Set> rv = new HashSet>(); + Set alreadyEquivalent = new HashSet(); + + List l = new ArrayList(g.getVertices()); + + for (V v1 : l) + { + if (alreadyEquivalent.contains(v1)) + continue; + + for (Iterator iterator = l.listIterator(l.indexOf(v1) + 1); iterator.hasNext();) { + V v2 = iterator.next(); + + if (alreadyEquivalent.contains(v2)) + continue; + + if (!canPossiblyCompare(v1, v2)) + continue; + + if (isStructurallyEquivalent(g, v1, v2)) { + Pair p = new Pair(v1, v2); + alreadyEquivalent.add(v2); + rv.add(p); + } + } + } + + return rv; + } + + /** + * Checks whether a pair of vertices are structurally equivalent. + * Specifically, whether v1's predecessors are equal to v2's predecessors, + * and same for successors. + * + * @param g the graph in which the structural equivalence comparison is to take place + * @param v1 the vertex to check for structural equivalence to v2 + * @param v2 the vertex to check for structural equivalence to v1 + */ + protected boolean isStructurallyEquivalent(Graph g, V v1, V v2) { + + if( g.degree(v1) != g.degree(v2)) { + return false; + } + + Set n1 = new HashSet(g.getPredecessors(v1)); + n1.remove(v2); + n1.remove(v1); + Set n2 = new HashSet(g.getPredecessors(v2)); + n2.remove(v1); + n2.remove(v2); + + Set o1 = new HashSet(g.getSuccessors(v1)); + Set o2 = new HashSet(g.getSuccessors(v2)); + o1.remove(v1); + o1.remove(v2); + o2.remove(v1); + o2.remove(v2); + + // this neglects self-loops and directed edges from 1 to other + boolean b = (n1.equals(n2) && o1.equals(o2)); + if (!b) + return b; + + // if there's a directed edge v1->v2 then there's a directed edge v2->v1 + b &= ( g.isSuccessor(v1, v2) == g.isSuccessor(v2, v1)); + + // self-loop check + b &= ( g.isSuccessor(v1, v1) == g.isSuccessor(v2, v2)); + + return b; + + } + + /** + * This is a space for optimizations. For example, for a bipartite graph, + * vertices from different partitions cannot possibly be compared. + * + * @param v1 + * @param v2 + */ + protected boolean canPossiblyCompare(V v1, V v2) { + return true; + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/VertexPartition.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/VertexPartition.java new file mode 100644 index 0000000000..b5ec5831ba --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/VertexPartition.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +/* + * Created on Feb 3, 2004 + */ +package edu.uci.ics.jung.algorithms.blockmodel; + +import java.util.*; + +import edu.uci.ics.jung.graph.Graph; + + +/** + * Maintains information about a vertex partition of a graph. + * This can be built from a map from vertices to vertex sets + * or from a collection of (disjoint) vertex sets, + * such as those created by various clustering methods. + */ +public class VertexPartition +{ + private Map> vertex_partition_map; + private Collection> vertex_sets; + private Graph graph; + + /** + * Creates an instance based on the specified graph and mapping from vertices + * to vertex sets, and generates a set of partitions based on this mapping. + * @param g the graph over which the vertex partition is defined + * @param partition_map the mapping from vertices to vertex sets (partitions) + */ + public VertexPartition(Graph g, Map> partition_map) + { + this.vertex_partition_map = Collections.unmodifiableMap(partition_map); + this.graph = g; + } + + /** + * Creates an instance based on the specified graph, vertex-set mapping, + * and set of disjoint vertex sets. The vertex-set mapping and vertex + * partitions must be consistent; that is, the mapping must reflect the + * division of vertices into partitions, and each vertex must appear in + * exactly one partition. + * @param g the graph over which the vertex partition is defined + * @param partition_map the mapping from vertices to vertex sets (partitions) + * @param vertex_sets the set of disjoint vertex sets + */ + public VertexPartition(Graph g, Map> partition_map, + Collection> vertex_sets) + { + this.vertex_partition_map = Collections.unmodifiableMap(partition_map); + this.vertex_sets = vertex_sets; + this.graph = g; + } + + /** + * Creates an instance based on the specified graph and set of disjoint vertex sets, + * and generates a vertex-to-partition map based on these sets. + * @param g the graph over which the vertex partition is defined + * @param vertex_sets the set of disjoint vertex sets + */ + public VertexPartition(Graph g, Collection> vertex_sets) + { + this.vertex_sets = vertex_sets; + this.graph = g; + } + + /** + * Returns the graph on which the partition is defined. + * @return the graph on which the partition is defined + */ + public Graph getGraph() + { + return graph; + } + + /** + * Returns a map from each vertex in the input graph to its partition. + * This map is generated if it does not already exist. + * @return a map from each vertex in the input graph to a vertex set + */ + public Map> getVertexToPartitionMap() + { + if (vertex_partition_map == null) + { + this.vertex_partition_map = new HashMap>(); + for (Set set : this.vertex_sets) + for (V v : set) + this.vertex_partition_map.put(v, set); + } + return vertex_partition_map; + } + + /** + * Returns a collection of vertex sets, where each vertex in the + * input graph is in exactly one set. + * This collection is generated based on the vertex-to-partition map + * if it does not already exist. + * @return a collection of vertex sets such that each vertex in the + * instance's graph is in exactly one set + */ + public Collection> getVertexPartitions() + { + if (vertex_sets == null) + { + this.vertex_sets = new HashSet>(); + this.vertex_sets.addAll(vertex_partition_map.values()); + } + return vertex_sets; + } + + /** + * Returns the number of partitions. + */ + public int numPartitions() + { + return vertex_sets.size(); + } + + @Override + public String toString() + { + return "Partitions: " + vertex_partition_map; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/package.html new file mode 100644 index 0000000000..d1cb06acae --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/package.html @@ -0,0 +1,33 @@ + + + + + + + +Support for establishing and maintaining graph element equivalence (such as in blockmodeling). +

    +In blockmodeling, groups of vertices are clustered together by similarity +(as if members of a "block" appearing on the diagonal of the graph's adjacency +matrix). +

    +This support currently includes: +

      +
    • VertexPartition: A class that maintains information on a +division of the vertices of a graph into disjoint sets. +
    • StructurallyEquivalent: An algorithm that finds sets of vertices that are +structurally equivalent. +
    + +

    + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/BicomponentClusterer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/BicomponentClusterer.java new file mode 100644 index 0000000000..aa697c7dbb --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/BicomponentClusterer.java @@ -0,0 +1,162 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.cluster; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.UndirectedGraph; + +/** + * Finds all biconnected components (bicomponents) of an undirected graph. + * A graph is a biconnected component if + * at least 2 vertices must be removed in order to disconnect the graph. (Graphs + * consisting of one vertex, or of two connected vertices, are also biconnected.) Biconnected + * components of three or more vertices have the property that every pair of vertices in the component + * are connected by two or more vertex-disjoint paths. + *

    + * Running time: O(|V| + |E|) where |V| is the number of vertices and |E| is the number of edges + * @see "Depth first search and linear graph algorithms by R. E. Tarjan (1972), SIAM J. Comp." + * + * @author Joshua O'Madadhain + */ +public class BicomponentClusterer implements Transformer, Set>> +{ + protected Map dfs_num; + protected Map high; + protected Map parents; + protected Stack stack; + protected int converse_depth; + + /** + * Constructs a new bicomponent finder + */ + public BicomponentClusterer() { + } + + /** + * Extracts the bicomponents from the graph. + * @param theGraph the graph whose bicomponents are to be extracted + * @return the ClusterSet of bicomponents + */ + public Set> transform(UndirectedGraph theGraph) + { + Set> bicomponents = new LinkedHashSet>(); + + if (theGraph.getVertices().isEmpty()) + return bicomponents; + + // initialize DFS number for each vertex to 0 + dfs_num = new HashMap(); + for (V v : theGraph.getVertices()) + { + dfs_num.put(v, 0); + } + + for (V v : theGraph.getVertices()) + { + if (dfs_num.get(v).intValue() == 0) // if we haven't hit this vertex yet... + { + high = new HashMap(); + stack = new Stack(); + parents = new HashMap(); + converse_depth = theGraph.getVertexCount(); + // find the biconnected components for this subgraph, starting from v + findBiconnectedComponents(theGraph, v, bicomponents); + + // if we only visited one vertex, this method won't have + // ID'd it as a biconnected component, so mark it as one + if (theGraph.getVertexCount() - converse_depth == 1) + { + Set s = new HashSet(); + s.add(v); + bicomponents.add(s); + } + } + } + + return bicomponents; + } + + /** + *

    Stores, in bicomponents, all the biconnected + * components that are reachable from v.

    + * + *

    The algorithm basically proceeds as follows: do a depth-first + * traversal starting from v, marking each vertex with + * a value that indicates the order in which it was encountered (dfs_num), + * and with + * a value that indicates the highest point in the DFS tree that is known + * to be reachable from this vertex using non-DFS edges (high). (Since it + * is measured on non-DFS edges, "high" tells you how far back in the DFS + * tree you can reach by two distinct paths, hence biconnectivity.) + * Each time a new vertex w is encountered, push the edge just traversed + * on a stack, and call this method recursively. If w.high is no greater than + * v.dfs_num, then the contents of the stack down to (v,w) is a + * biconnected component (and v is an articulation point, that is, a + * component boundary). In either case, set v.high to max(v.high, w.high), + * and continue. If w has already been encountered but is + * not v's parent, set v.high max(v.high, w.dfs_num) and continue. + * + *

    (In case anyone cares, the version of this algorithm on p. 224 of + * Udi Manber's "Introduction to Algorithms: A Creative Approach" seems to be + * wrong: the stack should be initialized outside this method, + * (v,w) should only be put on the stack if w hasn't been seen already, + * and there's no real benefit to putting v on the stack separately: just + * check for (v,w) on the stack rather than v. Had I known this, I could + * have saved myself a few days. JRTOM)

    + * + */ + protected void findBiconnectedComponents(UndirectedGraph g, V v, Set> bicomponents) + { + int v_dfs_num = converse_depth; + dfs_num.put(v, v_dfs_num); + converse_depth--; + high.put(v, v_dfs_num); + + for (V w : g.getNeighbors(v)) + { + int w_dfs_num = dfs_num.get(w).intValue();//get(w, dfs_num); + E vw = g.findEdge(v,w); + if (w_dfs_num == 0) // w hasn't yet been visited + { + parents.put(w, v); // v is w's parent in the DFS tree + stack.push(vw); + findBiconnectedComponents(g, w, bicomponents); + int w_high = high.get(w).intValue();//get(w, high); + if (w_high <= v_dfs_num) + { + // v disconnects w from the rest of the graph, + // i.e., v is an articulation point + // thus, everything between the top of the stack and + // v is part of a single biconnected component + Set bicomponent = new HashSet(); + E e; + do + { + e = stack.pop(); + bicomponent.addAll(g.getIncidentVertices(e)); + } + while (e != vw); + bicomponents.add(bicomponent); + } + high.put(v, Math.max(w_high, high.get(v).intValue())); + } + else if (w != parents.get(v)) // (v,w) is a back or a forward edge + high.put(v, Math.max(w_dfs_num, high.get(v).intValue())); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/EdgeBetweennessClusterer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/EdgeBetweennessClusterer.java new file mode 100644 index 0000000000..59e4605e35 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/EdgeBetweennessClusterer.java @@ -0,0 +1,109 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.cluster; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.BetweennessCentrality; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + + +/** + * An algorithm for computing clusters (community structure) in graphs based on edge betweenness. + * The betweenness of an edge is defined as the extent to which that edge lies along + * shortest paths between all pairs of nodes. + * + * This algorithm works by iteratively following the 2 step process: + *
      + *
    • Compute edge betweenness for all edges in current graph + *
    • Remove edge with highest betweenness + *
    + *

    + * Running time is: O(kmn) where k is the number of edges to remove, m is the total number of edges, and + * n is the total number of vertices. For very sparse graphs the running time is closer to O(kn^2) and for + * graphs with strong community structure, the complexity is even lower. + *

    + * This algorithm is a slight modification of the algorithm discussed below in that the number of edges + * to be removed is parameterized. + * @author Scott White + * @author Tom Nelson (converted to jung2) + * @see "Community structure in social and biological networks by Michelle Girvan and Mark Newman" + */ +public class EdgeBetweennessClusterer implements Transformer,Set>> { + private int mNumEdgesToRemove; + private Map> edges_removed; + + /** + * Constructs a new clusterer for the specified graph. + * @param numEdgesToRemove the number of edges to be progressively removed from the graph + */ + public EdgeBetweennessClusterer(int numEdgesToRemove) { + mNumEdgesToRemove = numEdgesToRemove; + edges_removed = new LinkedHashMap>(); + } + + /** + * Finds the set of clusters which have the strongest "community structure". + * The more edges removed the smaller and more cohesive the clusters. + * @param graph the graph + */ + public Set> transform(Graph graph) { + + if (mNumEdgesToRemove < 0 || mNumEdgesToRemove > graph.getEdgeCount()) { + throw new IllegalArgumentException("Invalid number of edges passed in."); + } + + edges_removed.clear(); + + for (int k=0;k bc = new BetweennessCentrality(graph); + E to_remove = null; + double score = 0; + for (E e : graph.getEdges()) + if (bc.getEdgeScore(e) > score) + { + to_remove = e; + score = bc.getEdgeScore(e); + } + edges_removed.put(to_remove, graph.getEndpoints(to_remove)); + graph.removeEdge(to_remove); + } + + WeakComponentClusterer wcSearch = new WeakComponentClusterer(); + Set> clusterSet = wcSearch.transform(graph); + + for (Map.Entry> entry : edges_removed.entrySet()) + { + Pair endpoints = entry.getValue(); + graph.addEdge(entry.getKey(), endpoints.getFirst(), endpoints.getSecond()); + } + return clusterSet; + } + + /** + * Retrieves the list of all edges that were removed + * (assuming extract(...) was previously called). + * The edges returned + * are stored in order in which they were removed. + * + * @return the edges in the original graph + */ + public List getEdgesRemoved() + { + return new ArrayList(edges_removed.keySet()); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/VoltageClusterer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/VoltageClusterer.java new file mode 100644 index 0000000000..859c06307c --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/VoltageClusterer.java @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2004, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * + * Created on Aug 12, 2004 + */ +package edu.uci.ics.jung.algorithms.cluster; + +import edu.uci.ics.jung.algorithms.scoring.VoltageScorer; +import edu.uci.ics.jung.algorithms.util.DiscreteDistribution; +import edu.uci.ics.jung.algorithms.util.KMeansClusterer; +import edu.uci.ics.jung.algorithms.util.KMeansClusterer.NotEnoughClustersException; +import edu.uci.ics.jung.graph.Graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +/** + *

    Clusters vertices of a Graph based on their ranks as + * calculated by VoltageScorer. This algorithm is based on, + * but not identical with, the method described in the paper below. + * The primary difference is that Wu and Huberman assume a priori that the clusters + * are of approximately the same size, and therefore use a more complex + * method than k-means (which is used here) for determining cluster + * membership based on co-occurrence data.

    + * + *

    The algorithm proceeds as follows: + *

      + *
    • first, generate a set of candidate clusters as follows: + *
        + *
      • pick (widely separated) vertex pair, run VoltageScorer + *
      • group the vertices in two clusters according to their voltages + *
      • store resulting candidate clusters + *
      + *
    • second, generate k-1 clusters as follows: + *
        + *
      • pick a vertex v as a cluster 'seed' + *
        (Wu/Huberman: most frequent vertex in candidate clusters) + *
      • calculate co-occurrence over all candidate clusters of v with each other + * vertex + *
      • separate co-occurrence counts into high/low; + * high vertices constitute a cluster + *
      • remove v's vertices from candidate clusters; continue + *
      + *
    • finally, remaining unassigned vertices are assigned to the kth ("garbage") + * cluster. + *

    + * + *

    NOTE: Depending on how the co-occurrence data splits the data into + * clusters, the number of clusters returned by this algorithm may be less than the + * number of clusters requested. The number of clusters will never be more than + * the number requested, however.

    + * + * @author Joshua O'Madadhain + * @see "'Finding communities in linear time: a physics approach', Fang Wu and Bernardo Huberman, http://www.hpl.hp.com/research/idl/papers/linear/" + * @see VoltageScorer + * @see KMeansClusterer + */ +public class VoltageClusterer +{ + protected int num_candidates; + protected KMeansClusterer kmc; + protected Random rand; + protected Graph g; + + /** + * Creates an instance of a VoltageCluster with the specified parameters. + * These are mostly parameters that are passed directly to VoltageScorer + * and KMeansClusterer. + * + * @param num_candidates the number of candidate clusters to create + */ + public VoltageClusterer(Graph g, int num_candidates) + { + if (num_candidates < 1) + throw new IllegalArgumentException("must generate >=1 candidates"); + + this.num_candidates = num_candidates; + this.kmc = new KMeansClusterer(); + rand = new Random(); + this.g = g; + } + + protected void setRandomSeed(int random_seed) + { + rand = new Random(random_seed); + } + + /** + * Returns a community (cluster) centered around v. + * @param v the vertex whose community we wish to discover + */ + public Collection> getCommunity(V v) + { + return cluster_internal(v, 2); + } + + /** + * Clusters the vertices of g into + * num_clusters clusters, based on their connectivity. + * @param num_clusters the number of clusters to identify + */ + public Collection> cluster(int num_clusters) + { + return cluster_internal(null, num_clusters); + } + + /** + * Does the work of getCommunity and cluster. + * @param origin the vertex around which clustering is to be done + * @param num_clusters the (maximum) number of clusters to find + */ + protected Collection> cluster_internal(V origin, int num_clusters) + { + // generate candidate clusters + // repeat the following 'samples' times: + // * pick (widely separated) vertex pair, run VoltageScorer + // * use k-means to identify 2 communities in ranked graph + // * store resulting candidate communities + ArrayList v_array = new ArrayList(g.getVertices()); + + LinkedList> candidates = new LinkedList>(); + + for (int j = 0; j < num_candidates; j++) + { + V source; + if (origin == null) + source = v_array.get((int)(rand.nextDouble() * v_array.size())); + else + source = origin; + V target = null; + do + { + target = v_array.get((int)(rand.nextDouble() * v_array.size())); + } + while (source == target); + VoltageScorer vs = new VoltageScorer(g, source, target); + vs.evaluate(); + + Map voltage_ranks = new HashMap(); + for (V v : g.getVertices()) + voltage_ranks.put(v, new double[] {vs.getVertexScore(v)}); + +// addOneCandidateCluster(candidates, voltage_ranks); + addTwoCandidateClusters(candidates, voltage_ranks); + } + + // repeat the following k-1 times: + // * pick a vertex v as a cluster seed + // (Wu/Huberman: most frequent vertex in candidates) + // * calculate co-occurrence (in candidate clusters) + // of this vertex with all others + // * use k-means to separate co-occurrence counts into high/low; + // high vertices are a cluster + // * remove v's vertices from candidate clusters + + Collection> clusters = new LinkedList>(); + Set remaining = new HashSet(g.getVertices()); + + List seed_candidates = getSeedCandidates(candidates); + int seed_index = 0; + + for (int j = 0; j < (num_clusters - 1); j++) + { + if (remaining.isEmpty()) + break; + + V seed; + if (seed_index == 0 && origin != null) + seed = origin; + else + { + do { seed = seed_candidates.get(seed_index++); } + while (!remaining.contains(seed)); + } + + Map occur_counts = getObjectCounts(candidates, seed); + if (occur_counts.size() < 2) + break; + + // now that we have the counts, cluster them... + try + { + Collection> high_low = kmc.cluster(occur_counts, 2); + // ...get the cluster with the highest-valued centroid... + Iterator> h_iter = high_low.iterator(); + Map cluster1 = h_iter.next(); + Map cluster2 = h_iter.next(); + double[] centroid1 = DiscreteDistribution.mean(cluster1.values()); + double[] centroid2 = DiscreteDistribution.mean(cluster2.values()); + Set new_cluster; + if (centroid1[0] >= centroid2[0]) + new_cluster = cluster1.keySet(); + else + new_cluster = cluster2.keySet(); + + // ...remove the elements of new_cluster from each candidate... + for (Set cluster : candidates) + cluster.removeAll(new_cluster); + clusters.add(new_cluster); + remaining.removeAll(new_cluster); + } + catch (NotEnoughClustersException nece) + { + // all remaining vertices are in the same cluster + break; + } + } + + // identify remaining vertices (if any) as a 'garbage' cluster + if (!remaining.isEmpty()) + clusters.add(remaining); + + return clusters; + } + + /** + * Do k-means with three intervals and pick the + * smaller two clusters (presumed to be on the ends); this is closer to the Wu-Huberman method. + * @param candidates + * @param voltage_ranks + */ + protected void addTwoCandidateClusters(LinkedList> candidates, + Map voltage_ranks) + { + try + { + List> clusters = new ArrayList>(kmc.cluster(voltage_ranks, 3)); + boolean b01 = clusters.get(0).size() > clusters.get(1).size(); + boolean b02 = clusters.get(0).size() > clusters.get(2).size(); + boolean b12 = clusters.get(1).size() > clusters.get(2).size(); + if (b01 && b02) + { + candidates.add(clusters.get(1).keySet()); + candidates.add(clusters.get(2).keySet()); + } + else if (!b01 && b12) + { + candidates.add(clusters.get(0).keySet()); + candidates.add(clusters.get(2).keySet()); + } + else if (!b02 && !b12) + { + candidates.add(clusters.get(0).keySet()); + candidates.add(clusters.get(1).keySet()); + } + } + catch (NotEnoughClustersException e) + { + // no valid candidates, continue + } + } + + /** + * alternative to addTwoCandidateClusters(): cluster vertices by voltages into 2 clusters. + * We only consider the smaller of the two clusters returned + * by k-means to be a 'true' cluster candidate; the other is a garbage cluster. + * @param candidates + * @param voltage_ranks + */ + protected void addOneCandidateCluster(LinkedList> candidates, + Map voltage_ranks) + { + try + { + List> clusters; + clusters = new ArrayList>(kmc.cluster(voltage_ranks, 2)); + if (clusters.get(0).size() < clusters.get(1).size()) + candidates.add(clusters.get(0).keySet()); + else + candidates.add(clusters.get(1).keySet()); + } + catch (NotEnoughClustersException e) + { + // no valid candidates, continue + } + } + + /** + * Returns an array of cluster seeds, ranked in decreasing order + * of number of appearances in the specified collection of candidate + * clusters. + * @param candidates + */ + protected List getSeedCandidates(Collection> candidates) + { + final Map occur_counts = getObjectCounts(candidates, null); + + ArrayList occurrences = new ArrayList(occur_counts.keySet()); + Collections.sort(occurrences, new MapValueArrayComparator(occur_counts)); + + System.out.println("occurrences: "); + for (int i = 0; i < occurrences.size(); i++) + System.out.println(occur_counts.get(occurrences.get(i))[0]); + + return occurrences; + } + + protected Map getObjectCounts(Collection> candidates, V seed) + { + Map occur_counts = new HashMap(); + for (V v : g.getVertices()) + occur_counts.put(v, new double[]{0}); + + for (Set candidate : candidates) + { + if (seed == null) + System.out.println(candidate.size()); + if (seed == null || candidate.contains(seed)) + { + for (V element : candidate) + { + double[] count = occur_counts.get(element); + count[0]++; + } + } + } + + if (seed == null) + { + System.out.println("occur_counts size: " + occur_counts.size()); + for (V v : occur_counts.keySet()) + System.out.println(occur_counts.get(v)[0]); + } + + return occur_counts; + } + + protected class MapValueArrayComparator implements Comparator + { + private Map map; + + protected MapValueArrayComparator(Map map) + { + this.map = map; + } + + public int compare(V o1, V o2) + { + double[] count0 = map.get(o1); + double[] count1 = map.get(o2); + if (count0[0] < count1[0]) + return 1; + else if (count0[0] > count1[0]) + return -1; + return 0; + } + + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClusterer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClusterer.java new file mode 100644 index 0000000000..cb79a78448 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClusterer.java @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.cluster; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.collections15.Buffer; +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.buffer.UnboundedFifoBuffer; + +import edu.uci.ics.jung.graph.Graph; + + + +/** + * Finds all weak components in a graph as sets of vertex sets. A weak component is defined as + * a maximal subgraph in which all pairs of vertices in the subgraph are reachable from one + * another in the underlying undirected subgraph. + *

    This implementation identifies components as sets of vertex sets. + * To create the induced graphs from any or all of these vertex sets, + * see algorithms.filters.FilterUtils. + *

    + * Running time: O(|V| + |E|) where |V| is the number of vertices and |E| is the number of edges. + * @author Scott White + */ +public class WeakComponentClusterer implements Transformer, Set>> +{ + /** + * Extracts the weak components from a graph. + * @param graph the graph whose weak components are to be extracted + * @return the list of weak components + */ + public Set> transform(Graph graph) { + + Set> clusterSet = new HashSet>(); + + HashSet unvisitedVertices = new HashSet(graph.getVertices()); + + while (!unvisitedVertices.isEmpty()) { + Set cluster = new HashSet(); + V root = unvisitedVertices.iterator().next(); + unvisitedVertices.remove(root); + cluster.add(root); + + Buffer queue = new UnboundedFifoBuffer(); + queue.add(root); + + while (!queue.isEmpty()) { + V currentVertex = queue.remove(); + Collection neighbors = graph.getNeighbors(currentVertex); + + for(V neighbor : neighbors) { + if (unvisitedVertices.contains(neighbor)) { + queue.add(neighbor); + unvisitedVertices.remove(neighbor); + cluster.add(neighbor); + } + } + } + clusterSet.add(cluster); + } + return clusterSet; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/package.html new file mode 100644 index 0000000000..f8bdb2279a --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/cluster/package.html @@ -0,0 +1,35 @@ + + + + + + + +Mechanisms for identifying clusters in graphs. Where these clusters define disjoint sets of vertices, +they may be used to define a VertexPartition for more convenient manipulation of the vertex/set +relationships. + +Current clustering algorithms include: +

      +
    • BicomponentClusterer: finds all subsets of vertices for which at least +2 vertices must be removed in order to disconnect the induced subgraphs. +
    • EdgeBetweennessClusterer: identifies vertex clusters by removing the edges of the highest +'betweenness' scores (see the importance/scoring package). +
    • VoltageClusterer: Clusters vertices based on their ranks as +calculated by VoltageRanker. +
    • WeakComponentVertexClusterer: Clusters vertices based on their membership in weakly +connected components of a graph. +
    + + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/EdgePredicateFilter.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/EdgePredicateFilter.java new file mode 100644 index 0000000000..5e3be06d18 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/EdgePredicateFilter.java @@ -0,0 +1,70 @@ +/* + * Created on May 19, 2008 + * + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.filters; + +import org.apache.commons.collections15.Predicate; + +import edu.uci.ics.jung.graph.Graph; + +/** + * Transforms the input graph into one which contains only those edges + * that pass the specified Predicate. The filtered graph + * is a copy of the original graph (same type, uses the same vertex and + * edge objects). All vertices from the original graph + * are copied into the new graph (even if they are not incident to any + * edges in the new graph). + * + * @author Joshua O'Madadhain + */ +public class EdgePredicateFilter implements Filter +{ + protected Predicate edge_pred; + + /** + * Creates an instance based on the specified edge Predicate. + * @param edge_pred the predicate that specifies which edges to add to the filtered graph + */ + public EdgePredicateFilter(Predicate edge_pred) + { + this.edge_pred = edge_pred; + } + + @SuppressWarnings("unchecked") + public Graph transform(Graph g) + { + Graph filtered; + try + { + filtered = g.getClass().newInstance(); + } + catch (InstantiationException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + + for (V v : g.getVertices()) + filtered.addVertex(v); + + for (E e : g.getEdges()) + { + if (edge_pred.evaluate(e)) + filtered.addEdge(e, g.getIncidentVertices(e)); + } + + return filtered; + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/Filter.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/Filter.java new file mode 100644 index 0000000000..a62895cc43 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/Filter.java @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.filters; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Graph; + + + +/** + * An interface for classes that return a subset of the input Graph + * as a Graph. The Graph returned may be either a + * new graph or a view into an existing graph; the documentation for the filter + * must specify which. + * + * @author danyelf + */ +public interface Filter extends Transformer, Graph>{ } diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/FilterUtils.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/FilterUtils.java new file mode 100644 index 0000000000..4845c0f37b --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/FilterUtils.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * Created on Jun 7, 2008 + * + */ +package edu.uci.ics.jung.algorithms.filters; + +import java.util.ArrayList; +import java.util.Collection; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Utility methods relating to filtering. + */ +public class FilterUtils +{ + /** + * Creates the induced subgraph from graph whose vertex set + * is equal to vertices. The graph returned has + * vertices as its vertex set, and includes all edges from + * graph which are incident only to elements of + * vertices. + * + * @param the vertex type + * @param the edge type + * @param vertices the subset of graph's vertices around + * which the subgraph is to be constructed + * @param graph the graph whose subgraph is to be constructed + * @return the subgraph induced by vertices + * @throws IllegalArgumentException if any vertex in + * vertices is not in graph + */ + @SuppressWarnings("unchecked") + public static > G createInducedSubgraph(Collection + vertices, G graph) + { + G subgraph = null; + try + { + subgraph = (G)graph.getClass().newInstance(); + + for (V v : vertices) + { + if (!graph.containsVertex(v)) + throw new IllegalArgumentException("Vertex " + v + + " is not an element of " + graph); + subgraph.addVertex(v); + } + + for (E e : graph.getEdges()) + { + Collection incident = graph.getIncidentVertices(e); + if (vertices.containsAll(incident)) + subgraph.addEdge(e, incident, graph.getEdgeType(e)); + } + } + catch (InstantiationException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + return subgraph; + } + + /** + * Creates the induced subgraphs of graph associated with each + * element of vertex_collections. + * Note that these vertex collections need not be disjoint. + * @param the vertex type + * @param the edge type + * @param vertex_collections the collections of vertex collections to be + * used to induce the subgraphs + * @param graph the graph whose subgraphs are to be created + * @return the induced subgraphs of graph associated with each + * element of vertex_collections + */ + public static > Collection + createAllInducedSubgraphs(Collection> + vertex_collections, G graph) + { + Collection subgraphs = new ArrayList(); + + for (Collection vertex_set : vertex_collections) + subgraphs.add(createInducedSubgraph(vertex_set, graph)); + + return subgraphs; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/KNeighborhoodFilter.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/KNeighborhoodFilter.java new file mode 100644 index 0000000000..62bcfc29b5 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/KNeighborhoodFilter.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +/* + * Created on Dec 26, 2001 + * + */ +package edu.uci.ics.jung.algorithms.filters; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import edu.uci.ics.jung.algorithms.filters.Filter; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * A filter used to extract the k-neighborhood around one or more root node(s). + * The k-neighborhood is defined as the subgraph induced by the set of + * vertices that are k or fewer hops (unweighted shortest-path distance) + * away from the root node. + * + * @author Danyel Fisher + */ +public class KNeighborhoodFilter implements Filter { + + /** + * The type of edge to follow for defining the neighborhood. + */ + public static enum EdgeType { IN_OUT, IN, OUT } + private Set rootNodes; + private int radiusK; + private EdgeType edgeType; + + /** + * Constructs a new instance of the filter. + * @param rootNodes the set of root nodes + * @param radiusK the neighborhood radius around the root set + * @param edgeType 0 for in/out edges, 1 for in-edges, 2 for out-edges + */ + public KNeighborhoodFilter(Set rootNodes, int radiusK, EdgeType edgeType) { + this.rootNodes = rootNodes; + this.radiusK = radiusK; + this.edgeType = edgeType; + } + + /** + * Constructs a new instance of the filter. + * @param rootNode the root node + * @param radiusK the neighborhood radius around the root set + * @param edgeType 0 for in/out edges, 1 for in-edges, 2 for out-edges + */ + public KNeighborhoodFilter(V rootNode, int radiusK, EdgeType edgeType) { + this.rootNodes = new HashSet(); + this.rootNodes.add(rootNode); + this.radiusK = radiusK; + this.edgeType = edgeType; + } + + /** + * Constructs an unassembled graph containing the k-neighborhood around the root node(s). + */ + @SuppressWarnings("unchecked") + public Graph transform(Graph graph) { + // generate a Set of Vertices we want + // add all to the UG + int currentDepth = 0; + List currentVertices = new ArrayList(); + Set visitedVertices = new HashSet(); + Set visitedEdges = new HashSet(); + Set acceptedVertices = new HashSet(); + //Copy, mark, and add all the root nodes to the new subgraph + for (V currentRoot : rootNodes) { + + visitedVertices.add(currentRoot); + acceptedVertices.add(currentRoot); + currentVertices.add(currentRoot); + } + ArrayList newVertices = null; + //Use BFS to locate the neighborhood around the root nodes within distance k + while (currentDepth < radiusK) { + newVertices = new ArrayList(); + for (V currentVertex : currentVertices) { + + Collection edges = null; + switch (edgeType) { + case IN_OUT : + edges = graph.getIncidentEdges(currentVertex); + break; + case IN : + edges = graph.getInEdges(currentVertex); + break; + case OUT : + edges = graph.getOutEdges(currentVertex); + break; + } + for (E currentEdge : edges) { + + V currentNeighbor = + graph.getOpposite(currentVertex, currentEdge); + if (!visitedEdges.contains(currentEdge)) { + visitedEdges.add(currentEdge); + if (!visitedVertices.contains(currentNeighbor)) { + visitedVertices.add(currentNeighbor); + acceptedVertices.add(currentNeighbor); + newVertices.add(currentNeighbor); + } + } + } + } + currentVertices = newVertices; + currentDepth++; + } + Graph ug = null; + try { + ug = graph.getClass().newInstance(); + for(E edge : graph.getEdges()) { + Pair endpoints = graph.getEndpoints(edge); + if(acceptedVertices.containsAll(endpoints)) { + ug.addEdge(edge, endpoints.getFirst(), endpoints.getSecond()); + } + } + } + catch (InstantiationException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + return ug; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/VertexPredicateFilter.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/VertexPredicateFilter.java new file mode 100644 index 0000000000..4543b424dc --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/VertexPredicateFilter.java @@ -0,0 +1,75 @@ +/* + * Created on May 19, 2008 + * + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.filters; + +import java.util.Collection; + +import org.apache.commons.collections15.Predicate; + +import edu.uci.ics.jung.graph.Graph; + +/** + * Transforms the input graph into one which contains only those vertices + * that pass the specified Predicate. The filtered graph + * is a copy of the original graph (same type, uses the same vertex and + * edge objects). Only those edges whose entire incident vertex collection + * passes the predicate are copied into the new graph. + * + * @author Joshua O'Madadhain + */ +public class VertexPredicateFilter implements Filter +{ + protected Predicate vertex_pred; + + /** + * Creates an instance based on the specified vertex Predicate. + * @param vertex_pred the predicate that specifies which vertices to add to the filtered graph + */ + public VertexPredicateFilter(Predicate vertex_pred) + { + this.vertex_pred = vertex_pred; + } + + @SuppressWarnings("unchecked") + public Graph transform(Graph g) + { + Graph filtered; + try + { + filtered = g.getClass().newInstance(); + } + catch (InstantiationException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + + for (V v : g.getVertices()) + if (vertex_pred.evaluate(v)) + filtered.addVertex(v); + + Collection filtered_vertices = filtered.getVertices(); + + for (E e : g.getEdges()) + { + Collection incident = g.getIncidentVertices(e); + if (filtered_vertices.containsAll(incident)) + filtered.addEdge(e, incident); + } + + return filtered; + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/package.html new file mode 100644 index 0000000000..0f9a018f88 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/filters/package.html @@ -0,0 +1,31 @@ + + + + + + + +Filtering mechanisms that produce subgraphs of an original graph. +Currently includes: +
      +
    • Filter: an interface for graph filters +
    • {Edge,Vertex}PredicateFilter: graph filters that return the +induced subgraph according to the +specified edge or vertex Predicate, respectively. +
    • KNeighborhoodFilter: a filter that returns the subgraph +induced by vertices within (unweighted) distance k of a specified vertex. +
    + + + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/flows/EdmondsKarpMaxFlow.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/flows/EdmondsKarpMaxFlow.java new file mode 100644 index 0000000000..af9ee34c4c --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/flows/EdmondsKarpMaxFlow.java @@ -0,0 +1,314 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.flows; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Buffer; +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.buffer.UnboundedFifoBuffer; + +import edu.uci.ics.jung.algorithms.util.IterativeProcess; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; + + +/** + * Implements the Edmonds-Karp maximum flow algorithm for solving the maximum flow problem. + * After the algorithm is executed, + * the input {@code Map} is populated with a {@code Number} for each edge that indicates + * the flow along that edge. + *

    + * An example of using this algorithm is as follows: + *

    + * EdmondsKarpMaxFlow ek = new EdmondsKarpMaxFlow(graph, source, sink, edge_capacities, edge_flows, 
    + * edge_factory);
    + * ek.evaluate(); // This instructs the class to compute the max flow
    + * 
    + * + * @see "Introduction to Algorithms by Cormen, Leiserson, Rivest, and Stein." + * @see "Network Flows by Ahuja, Magnanti, and Orlin." + * @see "Theoretical improvements in algorithmic efficiency for network flow problems by Edmonds and Karp, 1972." + * @author Scott White, adapted to jung2 by Tom Nelson + */ +public class EdmondsKarpMaxFlow extends IterativeProcess { + + private DirectedGraph mFlowGraph; + private DirectedGraph mOriginalGraph; + private V source; + private V target; + private int mMaxFlow; + private Set mSourcePartitionNodes; + private Set mSinkPartitionNodes; + private Set mMinCutEdges; + + private Map residualCapacityMap = new HashMap(); + private Map parentMap = new HashMap(); + private Map parentCapacityMap = new HashMap(); + private Transformer edgeCapacityTransformer; + private Map edgeFlowMap; + private Factory edgeFactory; + + /** + * Constructs a new instance of the algorithm solver for a given graph, source, and sink. + * Source and sink vertices must be elements of the specified graph, and must be + * distinct. + * @param directedGraph the flow graph + * @param source the source vertex + * @param sink the sink vertex + * @param edgeCapacityTransformer the transformer that gets the capacity for each edge. + * @param edgeFlowMap the map where the solver will place the value of the flow for each edge + * @param edgeFactory used to create new edge instances for backEdges + */ + @SuppressWarnings("unchecked") + public EdmondsKarpMaxFlow(DirectedGraph directedGraph, V source, V sink, + Transformer edgeCapacityTransformer, Map edgeFlowMap, + Factory edgeFactory) { + + if(directedGraph.getVertices().contains(source) == false || + directedGraph.getVertices().contains(sink) == false) { + throw new IllegalArgumentException("source and sink vertices must be elements of the specified graph"); + } + if (source.equals(sink)) { + throw new IllegalArgumentException("source and sink vertices must be distinct"); + } + mOriginalGraph = directedGraph; + + this.source = source; + this.target = sink; + this.edgeFlowMap = edgeFlowMap; + this.edgeCapacityTransformer = edgeCapacityTransformer; + this.edgeFactory = edgeFactory; + try { + mFlowGraph = directedGraph.getClass().newInstance(); + for(E e : mOriginalGraph.getEdges()) { + mFlowGraph.addEdge(e, mOriginalGraph.getSource(e), + mOriginalGraph.getDest(e), EdgeType.DIRECTED); + } + for(V v : mOriginalGraph.getVertices()) { + mFlowGraph.addVertex(v); + } + + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + mMaxFlow = 0; + mSinkPartitionNodes = new HashSet(); + mSourcePartitionNodes = new HashSet(); + mMinCutEdges = new HashSet(); + } + + private void clearParentValues() { + parentMap.clear(); + parentCapacityMap.clear(); + parentCapacityMap.put(source, Integer.MAX_VALUE); + parentMap.put(source, source); + } + + protected boolean hasAugmentingPath() { + + mSinkPartitionNodes.clear(); + mSourcePartitionNodes.clear(); + mSinkPartitionNodes.addAll(mFlowGraph.getVertices()); + + Set visitedEdgesMap = new HashSet(); + Buffer queue = new UnboundedFifoBuffer(); + queue.add(source); + + while (!queue.isEmpty()) { + V currentVertex = queue.remove(); + mSinkPartitionNodes.remove(currentVertex); + mSourcePartitionNodes.add(currentVertex); + Number currentCapacity = parentCapacityMap.get(currentVertex); + + Collection neighboringEdges = mFlowGraph.getOutEdges(currentVertex); + + for (E neighboringEdge : neighboringEdges) { + + V neighboringVertex = mFlowGraph.getDest(neighboringEdge); + + Number residualCapacity = residualCapacityMap.get(neighboringEdge); + if (residualCapacity.intValue() <= 0 || visitedEdgesMap.contains(neighboringEdge)) + continue; + + V neighborsParent = parentMap.get(neighboringVertex); + Number neighborCapacity = parentCapacityMap.get(neighboringVertex); + int newCapacity = Math.min(residualCapacity.intValue(),currentCapacity.intValue()); + + if ((neighborsParent == null) || newCapacity > neighborCapacity.intValue()) { + parentMap.put(neighboringVertex, currentVertex); + parentCapacityMap.put(neighboringVertex, new Integer(newCapacity)); + visitedEdgesMap.add(neighboringEdge); + if (neighboringVertex != target) { + queue.add(neighboringVertex); + } + } + } + } + + boolean hasAugmentingPath = false; + Number targetsParentCapacity = parentCapacityMap.get(target); + if (targetsParentCapacity != null && targetsParentCapacity.intValue() > 0) { + updateResidualCapacities(); + hasAugmentingPath = true; + } + clearParentValues(); + return hasAugmentingPath; + } + + @Override + public void step() { + while (hasAugmentingPath()) { + } + computeMinCut(); +// return 0; + } + + private void computeMinCut() { + + for (E e : mOriginalGraph.getEdges()) { + + V source = mOriginalGraph.getSource(e); + V destination = mOriginalGraph.getDest(e); + if (mSinkPartitionNodes.contains(source) && mSinkPartitionNodes.contains(destination)) { + continue; + } + if (mSourcePartitionNodes.contains(source) && mSourcePartitionNodes.contains(destination)) { + continue; + } + if (mSinkPartitionNodes.contains(source) && mSourcePartitionNodes.contains(destination)) { + continue; + } + mMinCutEdges.add(e); + } + } + + /** + * Returns the value of the maximum flow from the source to the sink. + */ + public int getMaxFlow() { + return mMaxFlow; + } + + /** + * Returns the nodes which share the same partition (as defined by the min-cut edges) + * as the sink node. + */ + public Set getNodesInSinkPartition() { + return mSinkPartitionNodes; + } + + /** + * Returns the nodes which share the same partition (as defined by the min-cut edges) + * as the source node. + */ + public Set getNodesInSourcePartition() { + return mSourcePartitionNodes; + } + + /** + * Returns the edges in the minimum cut. + */ + public Set getMinCutEdges() { + return mMinCutEdges; + } + + /** + * Returns the graph for which the maximum flow is calculated. + */ + public DirectedGraph getFlowGraph() { + return mFlowGraph; + } + + @Override + protected void initializeIterations() { + parentCapacityMap.put(source, Integer.MAX_VALUE); + parentMap.put(source, source); + + List edgeList = new ArrayList(mFlowGraph.getEdges()); + + for (int eIdx=0;eIdx< edgeList.size();eIdx++) { + E edge = edgeList.get(eIdx); + Number capacity = edgeCapacityTransformer.transform(edge); + + if (capacity == null) { + throw new IllegalArgumentException("Edge capacities must be provided in Transformer passed to constructor"); + } + residualCapacityMap.put(edge, capacity); + + V source = mFlowGraph.getSource(edge); + V destination = mFlowGraph.getDest(edge); + + if(mFlowGraph.isPredecessor(source, destination) == false) { + E backEdge = edgeFactory.create(); + mFlowGraph.addEdge(backEdge, destination, source, EdgeType.DIRECTED); + residualCapacityMap.put(backEdge, 0); + } + } + } + + @Override + protected void finalizeIterations() { + + for (E currentEdge : mFlowGraph.getEdges()) { + Number capacity = edgeCapacityTransformer.transform(currentEdge); + + Number residualCapacity = residualCapacityMap.get(currentEdge); + if (capacity != null) { + Integer flowValue = new Integer(capacity.intValue()-residualCapacity.intValue()); + this.edgeFlowMap.put(currentEdge, flowValue); + } + } + + Set backEdges = new HashSet(); + for (E currentEdge: mFlowGraph.getEdges()) { + + if (edgeCapacityTransformer.transform(currentEdge) == null) { + backEdges.add(currentEdge); + } else { + residualCapacityMap.remove(currentEdge); + } + } + for(E e : backEdges) { + mFlowGraph.removeEdge(e); + } + } + + private void updateResidualCapacities() { + + Number augmentingPathCapacity = parentCapacityMap.get(target); + mMaxFlow += augmentingPathCapacity.intValue(); + V currentVertex = target; + V parentVertex = null; + while ((parentVertex = parentMap.get(currentVertex)) != currentVertex) { + E currentEdge = mFlowGraph.findEdge(parentVertex, currentVertex); + + Number residualCapacity = residualCapacityMap.get(currentEdge); + + residualCapacity = residualCapacity.intValue() - augmentingPathCapacity.intValue(); + residualCapacityMap.put(currentEdge, residualCapacity); + + E backEdge = mFlowGraph.findEdge(currentVertex, parentVertex); + residualCapacity = residualCapacityMap.get(backEdge); + residualCapacity = residualCapacity.intValue() + augmentingPathCapacity.intValue(); + residualCapacityMap.put(backEdge, residualCapacity); + currentVertex = parentVertex; + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/flows/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/flows/package.html new file mode 100644 index 0000000000..1ec243d845 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/flows/package.html @@ -0,0 +1,20 @@ + + + + + + + +Methods for calculating properties relating to network flows (such as max flow/min cut). + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/EvolvingGraphGenerator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/EvolvingGraphGenerator.java new file mode 100644 index 0000000000..d351f9b1ca --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/EvolvingGraphGenerator.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.generators; + + + +/** + * An interface for algorithms that generate graphs that evolve iteratively. + * @author Scott White + */ +public interface EvolvingGraphGenerator extends GraphGenerator { + + /** + * Instructs the algorithm to evolve the graph N steps. + * @param numSteps number of steps to iterate from the current state + */ + void evolveGraph(int numSteps); + + /** + * Retrieves the total number of steps elapsed. + * @return number of elapsed steps + */ + int numIterations(); +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/GraphGenerator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/GraphGenerator.java new file mode 100644 index 0000000000..a32906095f --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/GraphGenerator.java @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.generators; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.graph.Graph; + +/** + * An interface for algorithms that generate graphs. + * @author Scott White + */ +public interface GraphGenerator extends Factory>{ } diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/Lattice2DGenerator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/Lattice2DGenerator.java new file mode 100644 index 0000000000..e84425cebb --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/Lattice2DGenerator.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2009, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ + +package edu.uci.ics.jung.algorithms.generators; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * Simple generator of an m x n lattice where each vertex + * is incident with each of its neighbors (to the left, right, up, and down). + * May be toroidal, in which case the vertices on the edges are connected to + * their counterparts on the opposite edges as well. + * + *

    If the graph factory supplied has a default edge type of {@code EdgeType.DIRECTED}, + * then edges will be created in both directions between adjacent vertices. + * + * @author Joshua O'Madadhain + */ +public class Lattice2DGenerator implements GraphGenerator +{ + protected int row_count; + protected int col_count; + protected boolean is_toroidal; + protected boolean is_directed; + protected Factory> graph_factory; + protected Factory vertex_factory; + protected Factory edge_factory; + private List v_array; + + /** + * Constructs a generator of square lattices of size {@code latticeSize} + * with the specified parameters. + * + * @param graph_factory used to create the {@code Graph} for the lattice + * @param vertex_factory used to create the lattice vertices + * @param edge_factory used to create the lattice edges + * @param latticeSize the number of rows and columns of the lattice + * @param isToroidal if true, the created lattice wraps from top to bottom and left to right + */ + public Lattice2DGenerator(Factory> graph_factory, Factory vertex_factory, + Factory edge_factory, int latticeSize, boolean isToroidal) + { + this(graph_factory, vertex_factory, edge_factory, latticeSize, latticeSize, isToroidal); + } + + /** + * Creates a generator of {@code row_count} x {@code col_count} lattices + * with the specified parameters. + * + * @param graph_factory used to create the {@code Graph} for the lattice + * @param vertex_factory used to create the lattice vertices + * @param edge_factory used to create the lattice edges + * @param row_count the number of rows in the lattice + * @param col_count the number of columns in the lattice + * @param isToroidal if true, the created lattice wraps from top to bottom and left to right + */ + public Lattice2DGenerator(Factory> graph_factory, Factory vertex_factory, + Factory edge_factory, int row_count, int col_count, boolean isToroidal) + { + if (row_count < 2 || col_count < 2) + { + throw new IllegalArgumentException("Row and column counts must each be at least 2."); + } + + this.row_count = row_count; + this.col_count = col_count; + this.is_toroidal = isToroidal; + this.graph_factory = graph_factory; + this.vertex_factory = vertex_factory; + this.edge_factory = edge_factory; + this.is_directed = (graph_factory.create().getDefaultEdgeType() == EdgeType.DIRECTED); + } + + /** + * @see edu.uci.ics.jung.algorithms.generators.GraphGenerator#create() + */ + @SuppressWarnings("unchecked") + public Graph create() + { + int vertex_count = row_count * col_count; + Graph graph = graph_factory.create(); + v_array = new ArrayList(vertex_count); + for (int i = 0; i < vertex_count; i++) + { + V v = vertex_factory.create(); + graph.addVertex(v); + v_array.add(i, v); + } + + int start = is_toroidal ? 0 : 1; + int end_row = is_toroidal ? row_count : row_count - 1; + int end_col = is_toroidal ? col_count : col_count - 1; + + // fill in edges + // down + for (int i = 0; i < end_row; i++) + for (int j = 0; j < col_count; j++) + graph.addEdge(edge_factory.create(), getVertex(i,j), getVertex(i+1, j)); + // right + for (int i = 0; i < row_count; i++) + for (int j = 0; j < end_col; j++) + graph.addEdge(edge_factory.create(), getVertex(i,j), getVertex(i, j+1)); + + // if the graph is directed, fill in the edges going the other direction... + if (graph.getDefaultEdgeType() == EdgeType.DIRECTED) + { + // up + for (int i = start; i < row_count; i++) + for (int j = 0; j < col_count; j++) + graph.addEdge(edge_factory.create(), getVertex(i,j), getVertex(i-1, j)); + // left + for (int i = 0; i < row_count; i++) + for (int j = start; j < col_count; j++) + graph.addEdge(edge_factory.create(), getVertex(i,j), getVertex(i, j-1)); + } + + return graph; + } + + /** + * Returns the number of edges found in a lattice of this generator's specifications. + * (This is useful for subclasses that may modify the generated graphs to add more edges.) + */ + public int getGridEdgeCount() + { + int boundary_adjustment = (is_toroidal ? 0 : 1); + int vertical_edge_count = col_count * (row_count - boundary_adjustment); + int horizontal_edge_count = row_count * (col_count - boundary_adjustment); + + return (vertical_edge_count + horizontal_edge_count) * (is_directed ? 2 : 1); + } + + protected int getIndex(int i, int j) + { + return ((mod(i, row_count)) * col_count) + (mod(j, col_count)); + } + + protected int mod(int i, int modulus) + { + int i_mod = i % modulus; + return i_mod >= 0 ? i_mod : i_mod + modulus; + } + + /** + * Returns the vertex at position ({@code i mod row_count, j mod col_count}). + */ + protected V getVertex(int i, int j) + { + return v_array.get(getIndex(i, j)); + } + + /** + * Returns the {@code i}th vertex (counting row-wise). + */ + protected V getVertex(int i) + { + return v_array.get(i); + } + + /** + * Returns the row in which vertex {@code i} is found. + */ + protected int getRow(int i) + { + return i / row_count; + } + + /** + * Returns the column in which vertex {@code i} is found. + */ + protected int getCol(int i) + { + return i % col_count; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/package.html new file mode 100644 index 0000000000..441922dca5 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/package.html @@ -0,0 +1,20 @@ + + + + + + + +Methods for generating new (often random) graphs with various properties. + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/BarabasiAlbertGenerator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/BarabasiAlbertGenerator.java new file mode 100644 index 0000000000..77b419b4a4 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/BarabasiAlbertGenerator.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.algorithms.generators.EvolvingGraphGenerator; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.MultiGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + + +/** + *

    Simple evolving scale-free random graph generator. At each time + * step, a new vertex is created and is connected to existing vertices + * according to the principle of "preferential attachment", whereby + * vertices with higher degree have a higher probability of being + * selected for attachment.

    + * + *

    At a given timestep, the probability p of creating an edge + * between an existing vertex v and the newly added vertex is + *

    + * p = (degree(v) + 1) / (|E| + |V|);
    + * 
    + * + *

    where |E| and |V| are, respectively, the number + * of edges and vertices currently in the network (counting neither the new + * vertex nor the other edges that are being attached to it).

    + * + *

    Note that the formula specified in the original paper + * (cited below) was + *

    + * p = degree(v) / |E|
    + * 
    + *

    + * + *

    However, this would have meant that the probability of attachment for any existing + * isolated vertex would be 0. This version uses Lagrangian smoothing to give + * each existing vertex a positive attachment probability.

    + * + *

    The graph created may be either directed or undirected (controlled by a constructor + * parameter); the default is undirected. + * If the graph is specified to be directed, then the edges added will be directed + * from the newly added vertex u to the existing vertex v, with probability proportional to the + * indegree of v (number of edges directed towards v). If the graph is specified to be undirected, + * then the (undirected) edges added will connect u to v, with probability proportional to the + * degree of v.

    + * + *

    The parallel constructor parameter specifies whether parallel edges + * may be created.

    + * + * @see "A.-L. Barabasi and R. Albert, Emergence of scaling in random networks, Science 286, 1999." + * @author Scott White + * @author Joshua O'Madadhain + * @author Tom Nelson - adapted to jung2 + */ +public class BarabasiAlbertGenerator implements EvolvingGraphGenerator { + private Graph mGraph = null; + private int mNumEdgesToAttachPerStep; + private int mElapsedTimeSteps; + private Random mRandom; + protected List vertex_index; + protected int init_vertices; + protected Map index_vertex; + protected Factory> graphFactory; + protected Factory vertexFactory; + protected Factory edgeFactory; + + /** + * Constructs a new instance of the generator. + * @param init_vertices number of unconnected 'seed' vertices that the graph should start with + * @param numEdgesToAttach the number of edges that should be attached from the + * new vertex to pre-existing vertices at each time step + * @param directed specifies whether the graph and edges to be created should be directed or not + * @param parallel specifies whether the algorithm permits parallel edges + * @param seed random number seed + */ + public BarabasiAlbertGenerator(Factory> graphFactory, + Factory vertexFactory, Factory edgeFactory, + int init_vertices, int numEdgesToAttach, + int seed, Set seedVertices) + { + assert init_vertices > 0 : "Number of initial unconnected 'seed' vertices " + + "must be positive"; + assert numEdgesToAttach > 0 : "Number of edges to attach " + + "at each time step must be positive"; + + mNumEdgesToAttachPerStep = numEdgesToAttach; + mRandom = new Random(seed); + this.graphFactory = graphFactory; + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + this.init_vertices = init_vertices; + initialize(seedVertices); + } + + + /** + * Constructs a new instance of the generator, whose output will be an undirected graph, + * and which will use the current time as a seed for the random number generation. + * @param init_vertices number of vertices that the graph should start with + * @param numEdgesToAttach the number of edges that should be attached from the + * new vertex to pre-existing vertices at each time step + */ + public BarabasiAlbertGenerator(Factory> graphFactory, + Factory vertexFactory, Factory edgeFactory, + int init_vertices, int numEdgesToAttach, Set seedVertices) { + this(graphFactory, vertexFactory, edgeFactory, init_vertices, numEdgesToAttach, (int) System.currentTimeMillis(), seedVertices); + } + + private void initialize(Set seedVertices) { + + mGraph = graphFactory.create(); + + vertex_index = new ArrayList(2*init_vertices); + index_vertex = new HashMap(2*init_vertices); + for (int i = 0; i < init_vertices; i++) { + V v = vertexFactory.create(); + mGraph.addVertex(v); + vertex_index.add(v); + index_vertex.put(v, i); + seedVertices.add(v); + } + + mElapsedTimeSteps = 0; + } + + private void createRandomEdge(Collection preexistingNodes, + V newVertex, Set> added_pairs) { + V attach_point; + boolean created_edge = false; + Pair endpoints; + do { + attach_point = vertex_index.get(mRandom.nextInt(vertex_index.size())); + + endpoints = new Pair(newVertex, attach_point); + + // if parallel edges are not allowed, skip attach_point if + // already exists; note that because of the way edges are added, we only need to check + // the list of candidate edges for duplicates. + if (!(mGraph instanceof MultiGraph)) + { + if (added_pairs.contains(endpoints)) + continue; + if (mGraph.getDefaultEdgeType() == EdgeType.UNDIRECTED && + added_pairs.contains(new Pair(attach_point, newVertex))) + continue; + } + + double degree = mGraph.inDegree(attach_point); + + // subtract 1 from numVertices because we don't want to count newVertex + // (which has already been added to the graph, but not to vertex_index) + double attach_prob = (degree + 1) / (mGraph.getEdgeCount() + mGraph.getVertexCount() - 1); + if (attach_prob >= mRandom.nextDouble()) + created_edge = true; + } + while (!created_edge); + + added_pairs.add(endpoints); + + if (mGraph.getDefaultEdgeType() == EdgeType.UNDIRECTED) { + added_pairs.add(new Pair(attach_point, newVertex)); + } + } + + public void evolveGraph(int numTimeSteps) { + + for (int i = 0; i < numTimeSteps; i++) { + evolveGraph(); + mElapsedTimeSteps++; + } + } + + private void evolveGraph() { + Collection preexistingNodes = mGraph.getVertices(); + V newVertex = vertexFactory.create(); + + mGraph.addVertex(newVertex); + + // generate and store the new edges; don't add them to the graph + // yet because we don't want to bias the degree calculations + // (all new edges in a timestep should be added in parallel) + Set> added_pairs = new HashSet>(mNumEdgesToAttachPerStep*3); + + for (int i = 0; i < mNumEdgesToAttachPerStep; i++) + createRandomEdge(preexistingNodes, newVertex, added_pairs); + + for (Pair pair : added_pairs) + { + V v1 = pair.getFirst(); + V v2 = pair.getSecond(); + if (mGraph.getDefaultEdgeType() != EdgeType.UNDIRECTED || + !mGraph.isNeighbor(v1, v2)) + mGraph.addEdge(edgeFactory.create(), pair); + } + // now that we're done attaching edges to this new vertex, + // add it to the index + vertex_index.add(newVertex); + index_vertex.put(newVertex, new Integer(vertex_index.size() - 1)); + } + + public int numIterations() { + return mElapsedTimeSteps; + } + + public Graph create() { + return mGraph; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/EppsteinPowerLawGenerator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/EppsteinPowerLawGenerator.java new file mode 100644 index 0000000000..e3bf04b68d --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/EppsteinPowerLawGenerator.java @@ -0,0 +1,128 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.algorithms.generators.GraphGenerator; +import edu.uci.ics.jung.graph.Graph; + +/** + * Graph generator that generates undirected graphs with power-law degree distributions. + * @author Scott White + * @see "A Steady State Model for Graph Power Law by David Eppstein and Joseph Wang" + */ +public class EppsteinPowerLawGenerator implements GraphGenerator { + private int mNumVertices; + private int mNumEdges; + private int mNumIterations; + private double mMaxDegree; + private Random mRandom; + private Factory> graphFactory; + private Factory vertexFactory; + private Factory edgeFactory; + + /** + * Creates an instance with the specified factories and specifications. + * @param graphFactory the factory to use to generate the graph + * @param vertexFactory the factory to use to create vertices + * @param edgeFactory the factory to use to create edges + * @param numVertices the number of vertices for the generated graph + * @param numEdges the number of edges the generated graph will have, should be Theta(numVertices) + * @param r the number of iterations to use; the larger the value the better the graph's degree + * distribution will approximate a power-law + */ + public EppsteinPowerLawGenerator(Factory> graphFactory, + Factory vertexFactory, Factory edgeFactory, + int numVertices, int numEdges, int r) { + this.graphFactory = graphFactory; + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + mNumVertices = numVertices; + mNumEdges = numEdges; + mNumIterations = r; + mRandom = new Random(); + } + + protected Graph initializeGraph() { + Graph graph = null; + graph = graphFactory.create(); + for(int i=0; i vertices = new ArrayList(graph.getVertices()); + while (graph.getEdgeCount() < mNumEdges) { + V u = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + V v = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + if (!graph.isSuccessor(v,u)) { + graph.addEdge(edgeFactory.create(), u, v); + } + } + + double maxDegree = 0; + for (V v : graph.getVertices()) { + maxDegree = Math.max(graph.degree(v),maxDegree); + } + mMaxDegree = maxDegree; //(maxDegree+1)*(maxDegree)/2; + + return graph; + } + + /** + * Generates a graph whose degree distribution approximates a power-law. + * @return the generated graph + */ + public Graph create() { + Graph graph = initializeGraph(); + + List vertices = new ArrayList(graph.getVertices()); + for (int rIdx = 0; rIdx < mNumIterations; rIdx++) { + + V v = null; + int degree = 0; + do { + v = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + degree = graph.degree(v); + + } while (degree == 0); + + List edges = new ArrayList(graph.getIncidentEdges(v)); + E randomExistingEdge = edges.get((int) (mRandom.nextDouble()*degree)); + + // FIXME: look at email thread on a more efficient RNG for arbitrary distributions + + V x = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + V y = null; + do { + y = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + + } while (mRandom.nextDouble() > ((graph.degree(y)+1)/mMaxDegree)); + + if (!graph.isSuccessor(y,x) && x != y) { + graph.removeEdge(randomExistingEdge); + graph.addEdge(edgeFactory.create(), x, y); + } + } + + return graph; + } + + /** + * Sets the seed for the random number generator. + * @param seed input to the random number generator. + */ + public void setSeed(long seed) { + mRandom.setSeed(seed); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/ErdosRenyiGenerator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/ErdosRenyiGenerator.java new file mode 100644 index 0000000000..3a33730802 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/ErdosRenyiGenerator.java @@ -0,0 +1,100 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.algorithms.generators.GraphGenerator; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; + +/** + * Generates a random graph using the Erdos-Renyi binomial model + * (each pair of vertices is connected with probability p). + * + * @author William Giordano, Scott White, Joshua O'Madadhain + */ +public class ErdosRenyiGenerator implements GraphGenerator { + private int mNumVertices; + private double mEdgeConnectionProbability; + private Random mRandom; + Factory> graphFactory; + Factory vertexFactory; + Factory edgeFactory; + + /** + * + * @param numVertices number of vertices graph should have + * @param p Connection's probability between 2 vertices + */ + public ErdosRenyiGenerator(Factory> graphFactory, + Factory vertexFactory, Factory edgeFactory, + int numVertices,double p) + { + if (numVertices <= 0) { + throw new IllegalArgumentException("A positive # of vertices must be specified."); + } + mNumVertices = numVertices; + if (p < 0 || p > 1) { + throw new IllegalArgumentException("p must be between 0 and 1."); + } + this.graphFactory = graphFactory; + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + mEdgeConnectionProbability = p; + mRandom = new Random(); + } + + /** + * Returns a graph in which each pair of vertices is connected by + * an undirected edge with the probability specified by the constructor. + */ + public Graph create() { + UndirectedGraph g = graphFactory.create(); + for(int i=0; i list = new ArrayList(g.getVertices()); + + for (int i = 0; i < mNumVertices-1; i++) { + V v_i = list.get(i); + for (int j = i+1; j < mNumVertices; j++) { + V v_j = list.get(j); + if (mRandom.nextDouble() < mEdgeConnectionProbability) { + g.addEdge(edgeFactory.create(), v_i, v_j); + } + } + } + return g; + } + + /** + * Sets the seed of the internal random number generator to {@code seed}. + * Enables consistent behavior. + */ + public void setSeed(long seed) { + mRandom.setSeed(seed); + } +} + + + + + + + + + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/KleinbergSmallWorldGenerator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/KleinbergSmallWorldGenerator.java new file mode 100644 index 0000000000..de01b69b5a --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/KleinbergSmallWorldGenerator.java @@ -0,0 +1,184 @@ + +package edu.uci.ics.jung.algorithms.generators.random; + +/* +* Copyright (c) 2009, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.algorithms.generators.Lattice2DGenerator; +import edu.uci.ics.jung.algorithms.util.WeightedChoice; +import edu.uci.ics.jung.graph.Graph; + +/** + * Graph generator that produces a random graph with small world properties. + * The underlying model is an mxn (optionally toroidal) lattice. Each node u + * has four local connections, one to each of its neighbors, and + * in addition 1+ long range connections to some node v where v is chosen randomly according to + * probability proportional to d^-alpha where d is the lattice distance between u and v and alpha + * is the clustering exponent. + * + * @see "Navigation in a small world J. Kleinberg, Nature 406(2000), 845." + * @author Joshua O'Madadhain + */ +public class KleinbergSmallWorldGenerator extends Lattice2DGenerator { + private double clustering_exponent; + private Random random; + private int num_connections = 1; + + /** + * Creates + * @param graph_factory + * @param vertex_factory + * @param edge_factory + * @param latticeSize + * @param clusteringExponent + */ + public KleinbergSmallWorldGenerator(Factory> graph_factory, Factory vertex_factory, + Factory edge_factory, int latticeSize, double clusteringExponent) + { + this(graph_factory, vertex_factory, edge_factory, latticeSize, latticeSize, clusteringExponent); + } + + /** + * @param graph_factory + * @param vertex_factory + * @param edge_factory + * @param row_count + * @param col_count + * @param clusteringExponent + */ + public KleinbergSmallWorldGenerator(Factory> graph_factory, Factory vertex_factory, + Factory edge_factory, int row_count, int col_count, double clusteringExponent) + { + super(graph_factory, vertex_factory, edge_factory, row_count, col_count, true); + clustering_exponent = clusteringExponent; + initialize(); + } + + /** + * @param graph_factory + * @param vertex_factory + * @param edge_factory + * @param row_count + * @param col_count + * @param clusteringExponent + * @param isToroidal + */ + public KleinbergSmallWorldGenerator(Factory> graph_factory, Factory vertex_factory, + Factory edge_factory, int row_count, int col_count, double clusteringExponent, + boolean isToroidal) + { + super(graph_factory, vertex_factory, edge_factory, row_count, col_count, isToroidal); + clustering_exponent = clusteringExponent; + initialize(); + } + + private void initialize() + { + this.random = new Random(); + } + + /** + * Sets the {@code Random} instance used by this instance. Useful for + * unit testing. + */ + public void setRandom(Random random) + { + this.random = random; + } + + /** + * Sets the seed of the internal random number generator. May be used to provide repeatable + * experiments. + */ + public void setRandomSeed(long seed) + { + random.setSeed(seed); + } + + /** + * Sets the number of new 'small-world' connections (outgoing edges) to be added to each vertex. + */ + public void setConnectionCount(int num_connections) + { + if (num_connections <= 0) + { + throw new IllegalArgumentException("Number of new connections per vertex must be >= 1"); + } + this.num_connections = num_connections; + } + + /** + * Returns the number of new 'small-world' connections to be made to each vertex. + */ + public int getConnectionCount() + { + return this.num_connections; + } + + /** + * Generates a random small world network according to the parameters given + * @return a random small world graph + */ + @Override + public Graph create() + { + Graph graph = super.create(); + + // TODO: For toroidal graphs, we can make this more clever by pre-creating the WeightedChoice object + // and using the output as an offset to the current vertex location. + WeightedChoice weighted_choice; + + // Add long range connections + for (int i = 0; i < graph.getVertexCount(); i++) + { + V source = getVertex(i); + int row = getRow(i); + int col = getCol(i); + int row_offset = row < row_count/2 ? -row_count : row_count; + int col_offset = col < col_count/2 ? -col_count : col_count; + + Map vertex_weights = new HashMap(); + for (int j = 0; j < row_count; j++) + { + for (int k = 0; k < col_count; k++) + { + if (j == row && k == col) + continue; + int v_dist = Math.abs(j - row); + int h_dist = Math.abs(k - col); + if (is_toroidal) + { + v_dist = Math.min(v_dist, Math.abs(j - row+row_offset)); + h_dist = Math.min(h_dist, Math.abs(k - col+col_offset)); + } + int distance = v_dist + h_dist; + if (distance < 2) + continue; + else + vertex_weights.put(getVertex(j,k), (float)Math.pow(distance, -clustering_exponent)); + } + } + + for (int j = 0; j < this.num_connections; j++) { + weighted_choice = new WeightedChoice(vertex_weights, random); + V target = weighted_choice.nextItem(); + graph.addEdge(edge_factory.create(), source, target); + } + } + + return graph; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/MixedRandomGraphGenerator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/MixedRandomGraphGenerator.java new file mode 100644 index 0000000000..a39a6404bd --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/MixedRandomGraphGenerator.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + */ +/* + * Created on Jul 2, 2003 + * + */ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * + * Generates a mixed-mode random graph based on the output of BarabasiAlbertGenerator. + * Primarily intended for providing a heterogeneous sample graph for visualization testing, etc. + * + */ +public class MixedRandomGraphGenerator { + + /** + * Equivalent to generateMixedRandomGraph(edge_weight, num_vertices, true). + */ + public static Graph generateMixedRandomGraph( + Factory> graphFactory, + Factory vertexFactory, + Factory edgeFactory, + Map edge_weight, + int num_vertices, Set seedVertices) + { + return generateMixedRandomGraph(graphFactory, vertexFactory, edgeFactory, + edge_weight, num_vertices, true, seedVertices); + } + + /** + * Returns a random mixed-mode graph. Starts with a randomly generated + * Barabasi-Albert (preferential attachment) generator + * (4 initial vertices, 3 edges added at each step, and num_vertices - 4 evolution steps). + * Then takes the resultant graph, replaces random undirected edges with directed + * edges, and assigns random weights to each edge. + */ + public static Graph generateMixedRandomGraph( + Factory> graphFactory, + Factory vertexFactory, + Factory edgeFactory, + Map edge_weights, + int num_vertices, boolean parallel, Set seedVertices) + { + int seed = (int)(Math.random() * 10000); + BarabasiAlbertGenerator bag = + new BarabasiAlbertGenerator(graphFactory, vertexFactory, edgeFactory, + 4, 3, //false, parallel, + seed, seedVertices); + bag.evolveGraph(num_vertices - 4); + Graph ug = bag.create(); + + // create a SparseMultigraph version of g + Graph g = graphFactory.create(); + //new SparseMultigraph(); + for(V v : ug.getVertices()) { + g.addVertex(v); + } + + // randomly replace some of the edges by directed edges to + // get a mixed-mode graph, add random weights + + for(E e : ug.getEdges()) { + V v1 = ug.getEndpoints(e).getFirst(); + V v2 = ug.getEndpoints(e).getSecond(); + + E me = edgeFactory.create(); + g.addEdge(me, v1, v2, Math.random() < .5 ? EdgeType.DIRECTED : EdgeType.UNDIRECTED); + edge_weights.put(me, Math.random()); + } + + return g; + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/package.html new file mode 100644 index 0000000000..9f85614a82 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/generators/random/package.html @@ -0,0 +1,28 @@ + + + + + + + +Methods for generating random graphs with various properties. These include: +
      +
    • BarabasiAlbertGenerator: scale-free graphs using the preferential attachment heuristic. +
    • EppsteinPowerLawGenerator: graphs whose degree distribution approximates a power law +
    • ErdosRenyiGenerator: graphs for which edges are created with a specified probability +
    • MixedRandomGraphGenerator: takes the output of BarabasiAlbertGenerator and +perturbs it to generate a mixed-mode analog with both directed and undirected edges. +
    • + + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/AbstractRanker.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/AbstractRanker.java new file mode 100644 index 0000000000..6ea8bc84a7 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/AbstractRanker.java @@ -0,0 +1,388 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.text.DecimalFormat; +import java.text.Format; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.map.LazyMap; + +import edu.uci.ics.jung.algorithms.util.IterativeProcess; +import edu.uci.ics.jung.graph.Graph; + +/** + * Abstract class for algorithms that rank nodes or edges by some "importance" metric. Provides a common set of + * services such as: + *
        + *
      • storing rank scores
      • + *
      • getters and setters for rank scores
      • + *
      • computing default edge weights
      • + *
      • normalizing default or user-provided edge transition weights
      • + *
      • normalizing rank scores
      • + *
      • automatic cleanup of decorations
      • + *
      • creation of Ranking list
      • + *
      • print rankings in sorted order by rank
      • + *
      + *

      + * By default, all rank scores are removed from the vertices (or edges) being ranked. + * @author Scott White + */ +public abstract class AbstractRanker extends IterativeProcess { + private Graph mGraph; + private List> mRankings; + private boolean mRemoveRankScoresOnFinalize; + private boolean mRankNodes; + private boolean mRankEdges; + private boolean mNormalizeRankings; + protected Map> vertexRankScores = + LazyMap.decorate( + new HashMap>(), + new Factory>() { + public Map create() { + return new HashMap(); + }}); + protected Map> edgeRankScores = + LazyMap.decorate( + new HashMap>(), + new Factory>() { + public Map create() { + return new HashMap(); + }}); + private Map edgeWeights = new HashMap(); + + protected void initialize(Graph graph, boolean isNodeRanker, + boolean isEdgeRanker) { + if (!isNodeRanker && !isEdgeRanker) + throw new IllegalArgumentException("Must rank edges, vertices, or both"); + mGraph = graph; + mRemoveRankScoresOnFinalize = true; + mNormalizeRankings = true; + mRankNodes = isNodeRanker; + mRankEdges = isEdgeRanker; + } + + /** + * @return all rankScores + */ + public Map> getVertexRankScores() { + return vertexRankScores; + } + + public Map> getEdgeRankScores() { + return edgeRankScores; + } + + /** + * @return the rankScores + */ + public Map getVertexRankScores(Object key) { + return vertexRankScores.get(key); + } + + public Map getEdgeRankScores(Object key) { + return edgeRankScores.get(key); + } + + protected Collection getVertices() { + return mGraph.getVertices(); + } + + protected int getVertexCount() { + return mGraph.getVertexCount(); + } + + protected Graph getGraph() { + return mGraph; + } + + @Override + public void reset() { + } + + /** + * Returns true if this ranker ranks nodes, and + * false otherwise. + */ + public boolean isRankingNodes() { + return mRankNodes; + } + + /** + * Returns true if this ranker ranks edges, and + * false otherwise. + */ + public boolean isRankingEdges() { + return mRankEdges; + } + + /** + * Instructs the ranker whether or not it should remove the rank scores from the nodes (or edges) once the ranks + * have been computed. + * @param removeRankScoresOnFinalize true if the rank scores are to be removed, false otherwise + */ + public void setRemoveRankScoresOnFinalize(boolean removeRankScoresOnFinalize) { + this.mRemoveRankScoresOnFinalize = removeRankScoresOnFinalize; + } + + protected void onFinalize(Object e) {} + + /** + * The user datum key used to store the rank score. + * @return the key + */ + abstract public Object getRankScoreKey(); + + + @Override + protected void finalizeIterations() { + List> sortedRankings = new ArrayList>(); + + int id = 1; + if (mRankNodes) { + for (V currentVertex : getVertices()) { + Ranking ranking = new Ranking(id,getVertexRankScore(currentVertex),currentVertex); + sortedRankings.add(ranking); + if (mRemoveRankScoresOnFinalize) { + this.vertexRankScores.get(getRankScoreKey()).remove(currentVertex); + } + id++; + onFinalize(currentVertex); + } + } + if (mRankEdges) { + for (E currentEdge : mGraph.getEdges()) { + + Ranking ranking = new Ranking(id,getEdgeRankScore(currentEdge),currentEdge); + sortedRankings.add(ranking); + if (mRemoveRankScoresOnFinalize) { + this.edgeRankScores.get(getRankScoreKey()).remove(currentEdge); + } + id++; + onFinalize(currentEdge); + } + } + + mRankings = sortedRankings; + Collections.sort(mRankings); + } + + /** + * Retrieves the list of ranking instances in descending sorted order by rank score + * If the algorithm is ranking edges, the instances will be of type EdgeRanking, otherwise + * if the algorithm is ranking nodes the instances will be of type NodeRanking + * @return the list of rankings + */ + public List> getRankings() { + return mRankings; + } + + /** + * Return a list of the top k rank scores. + * @param topKRankings the value of k to use + * @return list of rank scores + */ + public List getRankScores(int topKRankings) { + List scores = new ArrayList(); + int count=1; + for (Ranking currentRanking : getRankings()) { + if (count > topKRankings) { + return scores; + } + scores.add(currentRanking.rankScore); + count++; + } + + return scores; + } + + /** + * Given an edge or node, returns the corresponding rank score. This is a default + * implementation of getRankScore which assumes the decorations are of type MutableDouble. + * This method only returns legal values if setRemoveRankScoresOnFinalize(false) was called + * prior to evaluate(). + * @return the rank score value + */ + public double getVertexRankScore(V v) { + Number rankScore = vertexRankScores.get(getRankScoreKey()).get(v); + if (rankScore != null) { + return rankScore.doubleValue(); + } else { + throw new RuntimeException("setRemoveRankScoresOnFinalize(false) must be called before evaluate()."); + } + } + + public double getVertexRankScore(V v, Object key) { + return vertexRankScores.get(key).get(v).doubleValue(); + } + + public double getEdgeRankScore(E e) { + Number rankScore = edgeRankScores.get(getRankScoreKey()).get(e); + if (rankScore != null) { + return rankScore.doubleValue(); + } else { + throw new RuntimeException("setRemoveRankScoresOnFinalize(false) must be called before evaluate()."); + } + } + + public double getEdgeRankScore(E e, Object key) { + return edgeRankScores.get(key).get(e).doubleValue(); + } + + protected void setVertexRankScore(V v, double rankValue, Object key) { + vertexRankScores.get(key).put(v, rankValue); + } + + protected void setEdgeRankScore(E e, double rankValue, Object key) { + edgeRankScores.get(key).put(e, rankValue); + } + + protected void setVertexRankScore(V v, double rankValue) { + setVertexRankScore(v,rankValue, getRankScoreKey()); + } + + protected void setEdgeRankScore(E e, double rankValue) { + setEdgeRankScore(e, rankValue, getRankScoreKey()); + } + + protected void removeVertexRankScore(V v, Object key) { + vertexRankScores.get(key).remove(v); + } + + protected void removeEdgeRankScore(E e, Object key) { + edgeRankScores.get(key).remove(e); + } + + protected void removeVertexRankScore(V v) { + vertexRankScores.get(getRankScoreKey()).remove(v); + } + + protected void removeEdgeRankScore(E e) { + edgeRankScores.get(getRankScoreKey()).remove(e); + } + + protected double getEdgeWeight(E e) { + return edgeWeights.get(e).doubleValue(); + } + + protected void setEdgeWeight(E e, double weight) { + edgeWeights.put(e, weight); + } + + public void setEdgeWeights(Map edgeWeights) { + this.edgeWeights = edgeWeights; + } + + /** + * @return the edgeWeights + */ + public Map getEdgeWeights() { + return edgeWeights; + } + + protected void assignDefaultEdgeTransitionWeights() { + + for (V currentVertex : getVertices()) { + + Collection outgoingEdges = mGraph.getOutEdges(currentVertex); + + double numOutEdges = outgoingEdges.size(); + for (E currentEdge : outgoingEdges) { + setEdgeWeight(currentEdge,1.0/numOutEdges); + } + } + } + + protected void normalizeEdgeTransitionWeights() { + + for (V currentVertex : getVertices()) { + + Collection outgoingEdges = mGraph.getOutEdges(currentVertex); + + double totalEdgeWeight = 0; + for (E currentEdge : outgoingEdges) { + totalEdgeWeight += getEdgeWeight(currentEdge); + } + + for (E currentEdge : outgoingEdges) { + setEdgeWeight(currentEdge,getEdgeWeight(currentEdge)/totalEdgeWeight); + } + } + } + + protected void normalizeRankings() { + if (!mNormalizeRankings) { + return; + } + double totalWeight = 0; + + for (V currentVertex : getVertices()) { + totalWeight += getVertexRankScore(currentVertex); + } + + for (V currentVertex : getVertices()) { + setVertexRankScore(currentVertex,getVertexRankScore(currentVertex)/totalWeight); + } + } + + /** + * Print the rankings to standard out in descending order of rank score + * @param verbose if true, include information about the actual rank order as well as + * the original position of the vertex before it was ranked + * @param printScore if true, include the actual value of the rank score + */ + public void printRankings(boolean verbose,boolean printScore) { + double total = 0; + Format formatter = new DecimalFormat("#0.#######"); + int rank = 1; + + for (Ranking currentRanking : getRankings()) { + double rankScore = currentRanking.rankScore; + if (verbose) { + System.out.print("Rank " + rank + ": "); + if (printScore) { + System.out.print(formatter.format(rankScore)); + } + System.out.print("\tVertex Id: " + currentRanking.originalPos); + System.out.print(" (" + currentRanking.getRanked() + ")"); + System.out.println(); + } else { + System.out.print(rank + "\t"); + if (printScore) { + System.out.print(formatter.format(rankScore)); + } + System.out.println("\t" + currentRanking.originalPos); + + } + total += rankScore; + rank++; + } + + if (verbose) { + System.out.println("Total: " + formatter.format(total)); + } + } + + /** + * Allows the user to specify whether or not s/he wants the rankings to be normalized. + * In some cases, this will have no effect since the algorithm doesn't allow normalization + * as an option + * @param normalizeRankings + */ + public void setNormalizeRankings(boolean normalizeRankings) { + mNormalizeRankings = normalizeRankings; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/BetweennessCentrality.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/BetweennessCentrality.java new file mode 100644 index 0000000000..25906f206a --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/BetweennessCentrality.java @@ -0,0 +1,190 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import org.apache.commons.collections15.Buffer; +import org.apache.commons.collections15.buffer.UnboundedFifoBuffer; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; + +/** + * Computes betweenness centrality for each vertex and edge in the graph. The result is that each vertex + * and edge has a UserData element of type MutableDouble whose key is 'centrality.BetweennessCentrality'. + * Note: Many social network researchers like to normalize the betweenness values by dividing the values by + * (n-1)(n-2)/2. The values given here are unnormalized.

      + * + * A simple example of usage is: + *

      + * BetweennessCentrality ranker = new BetweennessCentrality(someGraph);
      + * ranker.evaluate();
      + * ranker.printRankings();
      + * 
      + * + * Running time is: O(n^2 + nm). + * @see "Ulrik Brandes: A Faster Algorithm for Betweenness Centrality. Journal of Mathematical Sociology 25(2):163-177, 2001." + * @author Scott White + * @author Tom Nelson converted to jung2 + */ + +public class BetweennessCentrality extends AbstractRanker { + + public static final String CENTRALITY = "centrality.BetweennessCentrality"; + + /** + * Constructor which initializes the algorithm + * @param g the graph whose nodes are to be analyzed + */ + public BetweennessCentrality(Graph g) { + initialize(g, true, true); + } + + public BetweennessCentrality(Graph g, boolean rankNodes) { + initialize(g, rankNodes, true); + } + + public BetweennessCentrality(Graph g, boolean rankNodes, boolean rankEdges) + { + initialize(g, rankNodes, rankEdges); + } + + protected void computeBetweenness(Graph graph) { + + Map decorator = new HashMap(); + Map bcVertexDecorator = + vertexRankScores.get(getRankScoreKey()); + bcVertexDecorator.clear(); + Map bcEdgeDecorator = + edgeRankScores.get(getRankScoreKey()); + bcEdgeDecorator.clear(); + + Collection vertices = graph.getVertices(); + + for (V s : vertices) { + + initializeData(graph,decorator); + + decorator.get(s).numSPs = 1; + decorator.get(s).distance = 0; + + Stack stack = new Stack(); + Buffer queue = new UnboundedFifoBuffer(); + queue.add(s); + + while (!queue.isEmpty()) { + V v = queue.remove(); + stack.push(v); + + for(V w : getGraph().getSuccessors(v)) { + + if (decorator.get(w).distance < 0) { + queue.add(w); + decorator.get(w).distance = decorator.get(v).distance + 1; + } + + if (decorator.get(w).distance == decorator.get(v).distance + 1) { + decorator.get(w).numSPs += decorator.get(v).numSPs; + decorator.get(w).predecessors.add(v); + } + } + } + + while (!stack.isEmpty()) { + V w = stack.pop(); + + for (V v : decorator.get(w).predecessors) { + + double partialDependency = (decorator.get(v).numSPs / decorator.get(w).numSPs); + partialDependency *= (1.0 + decorator.get(w).dependency); + decorator.get(v).dependency += partialDependency; + E currentEdge = getGraph().findEdge(v, w); + double edgeValue = bcEdgeDecorator.get(currentEdge).doubleValue(); + edgeValue += partialDependency; + bcEdgeDecorator.put(currentEdge, edgeValue); + } + if (w != s) { + double bcValue = bcVertexDecorator.get(w).doubleValue(); + bcValue += decorator.get(w).dependency; + bcVertexDecorator.put(w, bcValue); + } + } + } + + if(graph instanceof UndirectedGraph) { + for (V v : vertices) { + double bcValue = bcVertexDecorator.get(v).doubleValue(); + bcValue /= 2.0; + bcVertexDecorator.put(v, bcValue); + } + for (E e : graph.getEdges()) { + double bcValue = bcEdgeDecorator.get(e).doubleValue(); + bcValue /= 2.0; + bcEdgeDecorator.put(e, bcValue); + } + } + + for (V vertex : vertices) { + decorator.remove(vertex); + } + } + + private void initializeData(Graph g, Map decorator) { + for (V vertex : g.getVertices()) { + + Map bcVertexDecorator = vertexRankScores.get(getRankScoreKey()); + if(bcVertexDecorator.containsKey(vertex) == false) { + bcVertexDecorator.put(vertex, 0.0); + } + decorator.put(vertex, new BetweennessData()); + } + for (E e : g.getEdges()) { + + Map bcEdgeDecorator = edgeRankScores.get(getRankScoreKey()); + if(bcEdgeDecorator.containsKey(e) == false) { + bcEdgeDecorator.put(e, 0.0); + } + } + } + + /** + * the user datum key used to store the rank scores + * @return the key + */ + @Override + public String getRankScoreKey() { + return CENTRALITY; + } + + @Override + public void step() { + computeBetweenness(getGraph()); + } + + class BetweennessData { + double distance; + double numSPs; + List predecessors; + double dependency; + + BetweennessData() { + distance = -1; + numSPs = 0; + predecessors = new ArrayList(); + dependency = 0; + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/KStepMarkov.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/KStepMarkov.java new file mode 100644 index 0000000000..9ee4030ce3 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/KStepMarkov.java @@ -0,0 +1,135 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import edu.uci.ics.jung.graph.DirectedGraph; + + +/** + * Algorithm variant of PageRankWithPriors that computes the importance of a node based upon taking fixed-length random + * walks out from the root set and then computing the stationary probability of being at each node. Specifically, it computes + * the relative probability that the markov chain will spend at any particular node, given that it start in the root + * set and ends after k steps. + *

      + * A simple example of usage is: + *

      + * KStepMarkov ranker = new KStepMarkov(someGraph,rootSet,6,null);
      + * ranker.evaluate();
      + * ranker.printRankings();
      + * 
      + *

      + * + * @author Scott White + * @author Tom Nelson - adapter to jung2 + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + */ +public class KStepMarkov extends RelativeAuthorityRanker { + public final static String RANK_SCORE = "jung.algorithms.importance.KStepMarkovExperimental.RankScore"; + private final static String CURRENT_RANK = "jung.algorithms.importance.KStepMarkovExperimental.CurrentRank"; + private int mNumSteps; + HashMap mPreviousRankingsMap; + + /** + * Construct the algorihm instance and initializes the algorithm. + * @param graph the graph to be analyzed + * @param priors the set of root nodes + * @param k positive integer parameter which controls the relative tradeoff between a distribution "biased" towards + * R and the steady-state distribution which is independent of where the Markov-process started. Generally values + * between 4-8 are reasonable + * @param edgeWeights the weight for each edge + */ + public KStepMarkov(DirectedGraph graph, Set priors, int k, Map edgeWeights) { + super.initialize(graph,true,false); + mNumSteps = k; + setPriors(priors); + initializeRankings(); + if (edgeWeights == null) { + assignDefaultEdgeTransitionWeights(); + } else { + setEdgeWeights(edgeWeights); + } + normalizeEdgeTransitionWeights(); + } + + /** + * The user datum key used to store the rank scores. + * @return the key + */ + @Override + public String getRankScoreKey() { + return RANK_SCORE; + } + + protected void incrementRankScore(V v, double rankValue) { + double value = getVertexRankScore(v, RANK_SCORE); + value += rankValue; + setVertexRankScore(v, value, RANK_SCORE); + } + + protected double getCurrentRankScore(V v) { + return getVertexRankScore(v, CURRENT_RANK); + } + + protected void setCurrentRankScore(V v, double rankValue) { + setVertexRankScore(v, rankValue, CURRENT_RANK); + } + + protected void initializeRankings() { + mPreviousRankingsMap = new HashMap(); + for (V v : getVertices()) { + Set priors = getPriors(); + double numPriors = priors.size(); + + if (getPriors().contains(v)) { + setVertexRankScore(v, 1.0/ numPriors); + setCurrentRankScore(v, 1.0/ numPriors); + mPreviousRankingsMap.put(v,1.0/numPriors); + } else { + setVertexRankScore(v, 0); + setCurrentRankScore(v, 0); + mPreviousRankingsMap.put(v, 0); + } + } + } + @Override + public void step() { + + for (int i=0;i incomingEdges = getGraph().getInEdges(v); + + double currentPageRankSum = 0; + for (E e : incomingEdges) { + double currentWeight = getEdgeWeight(e); + currentPageRankSum += + mPreviousRankingsMap.get(getGraph().getOpposite(v,e)).doubleValue()*currentWeight; + } + setCurrentRankScore(v,currentPageRankSum); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/Ranking.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/Ranking.java new file mode 100644 index 0000000000..b96e559341 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/Ranking.java @@ -0,0 +1,77 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + + +/** + * Abstract data container for ranking objects. Stores common data relevant to both node and edge rankings, namely, + * the original position of the instance in the list and the actual ranking score. + * @author Scott White + */ +public class Ranking implements Comparable { + /** + * The original (0-indexed) position of the instance being ranked + */ + public int originalPos; + /** + * The actual rank score (normally between 0 and 1) + */ + public double rankScore; + + /** + * what is being ranked + */ + private V ranked; + + /** + * Constructor which allows values to be set on construction + * @param originalPos The original (0-indexed) position of the instance being ranked + * @param rankScore The actual rank score (normally between 0 and 1) + */ + public Ranking(int originalPos, double rankScore, V ranked) { + this.originalPos = originalPos; + this.rankScore = rankScore; + this.ranked = ranked; + } + + /** + * Compares two ranking based on the rank score. + * @param o The other ranking + * @return -1 if the other ranking is higher, 0 if they are equal, and 1 if this ranking is higher + */ + public int compareTo(Object o) { + + Ranking otherRanking = (Ranking) o; + return Double.compare(otherRanking.rankScore,rankScore); + } + + /** + * Returns the rank score as a string. + * @return the stringified rank score + */ + @Override + public String toString() { + return String.valueOf(rankScore); + } + + /** + * @return the ranked + */ + public V getRanked() { + return ranked; + } + + /** + * @param ranked the ranked to set + */ + public void setRanked(V ranked) { + this.ranked = ranked; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/RelativeAuthorityRanker.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/RelativeAuthorityRanker.java new file mode 100644 index 0000000000..b40ba8d4a6 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/RelativeAuthorityRanker.java @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +/** + * This class provides basic infrastructure for relative authority algorithms that compute the importance of nodes + * relative to one or more root nodes. The services provided are: + *

        + *
      • The set of root nodes (priors) is stored and maintained
      • + *
      • Getters and setters for the prior rank score are provided
      • + *
      + * + * @author Scott White + */ +public abstract class RelativeAuthorityRanker extends AbstractRanker { + private Set mPriors; + /** + * The default key used for the user datum key corresponding to prior rank scores. + */ + + protected Map priorRankScoreMap = new HashMap(); + /** + * Cleans up all of the prior rank scores on finalize. + */ + @Override + protected void finalizeIterations() { + super.finalizeIterations(); + priorRankScoreMap.clear(); + } + + /** + * Retrieves the value of the prior rank score. + * @param v the root node (prior) + * @return the prior rank score + */ + protected double getPriorRankScore(V v) { + return priorRankScoreMap.get(v).doubleValue(); + + } + + /** + * Allows the user to specify a value to set for the prior rank score + * @param v the root node (prior) + * @param value the score to set to + */ + public void setPriorRankScore(V v, double value) { + this.priorRankScoreMap.put(v, value); + } + + /** + * Retrieves the set of priors. + * @return the set of root nodes (priors) + */ + protected Set getPriors() { return mPriors; } + + /** + * Specifies which vertices are root nodes (priors). + * @param priors the root nodes + */ + protected void setPriors(Set priors) { mPriors = priors; } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/WeightedNIPaths.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/WeightedNIPaths.java new file mode 100644 index 0000000000..bd715ce7ed --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/importance/WeightedNIPaths.java @@ -0,0 +1,194 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.graph.DirectedGraph; + + + +/** + * This algorithm measures the importance of nodes based upon both the number and length of disjoint paths that lead + * to a given node from each of the nodes in the root set. Specifically the formula for measuring the importance of a + * node is given by: I(t|R) = sum_i=1_|P(r,t)|_{alpha^|p_i|} where alpha is the path decay coefficient, p_i is path i + * and P(r,t) is a set of maximum-sized node-disjoint paths from r to t. + *

      + * This algorithm uses heuristic breadth-first search to try and find the maximum-sized set of node-disjoint paths + * between two nodes. As such, it is not guaranteed to give exact answers. + *

      + * A simple example of usage is: + *

      + * WeightedNIPaths ranker = new WeightedNIPaths(someGraph,2.0,6,rootSet);
      + * ranker.evaluate();
      + * ranker.printRankings();
      + * 
      + * + * @author Scott White + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + */ +public class WeightedNIPaths extends AbstractRanker { + public final static String WEIGHTED_NIPATHS_KEY = "jung.algorithms.importance.WEIGHTED_NIPATHS_KEY"; + private double mAlpha; + private int mMaxDepth; + private Set mPriors; + private Map pathIndices = new HashMap(); + private Map roots = new HashMap(); + private Map> pathsSeenMap = new HashMap>(); + private Factory vertexFactory; + private Factory edgeFactory; + + /** + * Constructs and initializes the algorithm. + * @param graph the graph whose nodes are being measured for their importance + * @param alpha the path decay coefficient (>= 1); 2 is recommended + * @param maxDepth the maximal depth to search out from the root set + * @param priors the root set (starting vertices) + */ + public WeightedNIPaths(DirectedGraph graph, Factory vertexFactory, + Factory edgeFactory, double alpha, int maxDepth, Set priors) { + super.initialize(graph, true,false); + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + mAlpha = alpha; + mMaxDepth = maxDepth; + mPriors = priors; + for (V v : graph.getVertices()) { + super.setVertexRankScore(v, 0.0); + } + } + + protected void incrementRankScore(V v, double rankValue) { + setVertexRankScore(v, getVertexRankScore(v) + rankValue); + } + + protected void computeWeightedPathsFromSource(V root, int depth) { + + int pathIdx = 1; + + for (E e : getGraph().getOutEdges(root)) { + this.pathIndices.put(e, pathIdx); + this.roots.put(e, root); + newVertexEncountered(pathIdx, getGraph().getEndpoints(e).getSecond(), root); + pathIdx++; + } + + List edges = new ArrayList(); + + V virtualNode = vertexFactory.create(); + getGraph().addVertex(virtualNode); + E virtualSinkEdge = edgeFactory.create(); + + getGraph().addEdge(virtualSinkEdge, virtualNode, root); + edges.add(virtualSinkEdge); + + int currentDepth = 0; + while (currentDepth <= depth) { + + double currentWeight = Math.pow(mAlpha, -1.0 * currentDepth); + for (E currentEdge : edges) { + incrementRankScore(getGraph().getEndpoints(currentEdge).getSecond(),// + currentWeight); + } + + if ((currentDepth == depth) || (edges.size() == 0)) break; + + List newEdges = new ArrayList(); + + for (E currentSourceEdge : edges) { //Iterator sourceEdgeIt = edges.iterator(); sourceEdgeIt.hasNext();) { + Number sourcePathIndex = this.pathIndices.get(currentSourceEdge); + + // from the currentSourceEdge, get its opposite end + // then iterate over the out edges of that opposite end + V newDestVertex = getGraph().getEndpoints(currentSourceEdge).getSecond(); + Collection outs = getGraph().getOutEdges(newDestVertex); + for (E currentDestEdge : outs) { + V destEdgeRoot = this.roots.get(currentDestEdge); + V destEdgeDest = getGraph().getEndpoints(currentDestEdge).getSecond(); + + if (currentSourceEdge == virtualSinkEdge) { + newEdges.add(currentDestEdge); + continue; + } + if (destEdgeRoot == root) { + continue; + } + if (destEdgeDest == getGraph().getEndpoints(currentSourceEdge).getFirst()) {//currentSourceEdge.getSource()) { + continue; + } + Set pathsSeen = this.pathsSeenMap.get(destEdgeDest); + + if (pathsSeen == null) { + newVertexEncountered(sourcePathIndex.intValue(), destEdgeDest, root); + } else if (roots.get(destEdgeDest) != root) { + roots.put(destEdgeDest,root); + pathsSeen.clear(); + pathsSeen.add(sourcePathIndex); + } else if (!pathsSeen.contains(sourcePathIndex)) { + pathsSeen.add(sourcePathIndex); + } else { + continue; + } + + this.pathIndices.put(currentDestEdge, sourcePathIndex); + this.roots.put(currentDestEdge, root); + newEdges.add(currentDestEdge); + } + } + + edges = newEdges; + currentDepth++; + } + + getGraph().removeVertex(virtualNode); + } + + private void newVertexEncountered(int sourcePathIndex, V dest, V root) { + Set pathsSeen = new HashSet(); + pathsSeen.add(sourcePathIndex); + this.pathsSeenMap.put(dest, pathsSeen); + roots.put(dest, root); + } + + @Override + public void step() { + for (V v : mPriors) { + computeWeightedPathsFromSource(v, mMaxDepth); + } + + normalizeRankings(); +// return 0; + } + + /** + * Given a node, returns the corresponding rank score. This implementation of getRankScore assumes + * the decoration representing the rank score is of type MutableDouble. + * @return the rank score for this node + */ + @Override + public String getRankScoreKey() { + return WEIGHTED_NIPATHS_KEY; + } + + @Override + protected void onFinalize(Object udc) { + pathIndices.remove(udc); + roots.remove(udc); + pathsSeenMap.remove(udc); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java new file mode 100644 index 0000000000..b59dcfaa4c --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * Created on Jul 7, 2003 + * + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.functors.ChainedTransformer; +import org.apache.commons.collections15.functors.CloneTransformer; +import org.apache.commons.collections15.map.LazyMap; + +import edu.uci.ics.jung.graph.Graph; + +/** + * Abstract class for implementations of {@code Layout}. It handles some of the + * basic functions: storing coordinates, maintaining the dimensions, initializing + * the locations, maintaining locked vertices. + * + * @author Danyel Fisher, Scott White + * @author Tom Nelson - converted to jung2 + * @param the vertex type + * @param the edge type + */ +abstract public class AbstractLayout implements Layout { + + /** + * a set of vertices that should not move in relation to the + * other vertices + */ + private Set dontmove = new HashSet(); + + protected Dimension size; + protected Graph graph; + protected boolean initialized; + + protected Map locations = + LazyMap.decorate(new HashMap(), + new Transformer() { + public Point2D transform(V arg0) { + return new Point2D.Double(); + }}); + + + /** + * Creates an instance which does not initialize the vertex locations. + * + * @param graph the graph for which the layout algorithm is to be created. + */ + protected AbstractLayout(Graph graph) { + if (graph == null) + { + throw new IllegalArgumentException("Graph must be non-null"); + } + this.graph = graph; + } + + @SuppressWarnings("unchecked") + protected AbstractLayout(Graph graph, Transformer initializer) { + this.graph = graph; + Transformer chain = + ChainedTransformer.getInstance(initializer, CloneTransformer.getInstance()); + this.locations = LazyMap.decorate(new HashMap(), (Transformer)chain); + initialized = true; + } + + protected AbstractLayout(Graph graph, Dimension size) { + this.graph = graph; + this.size = size; + } + + @SuppressWarnings("unchecked") + protected AbstractLayout(Graph graph, Transformer initializer, Dimension size) { + this.graph = graph; + Transformer chain = + ChainedTransformer.getInstance(initializer, CloneTransformer.getInstance()); + this.locations = LazyMap.decorate(new HashMap(), (Transformer)chain); + this.size = size; + } + + public void setGraph(Graph graph) { + this.graph = graph; + if(size != null && graph != null) { + initialize(); + } + } + + /** + * When a visualization is resized, it presumably wants to fix the + * locations of the vertices and possibly to reinitialize its data. The + * current method calls initializeLocations followed by initialize_local. + */ + public void setSize(Dimension size) { + + if(size != null && graph != null) { + + Dimension oldSize = this.size; + this.size = size; + initialize(); + + if(oldSize != null) { + adjustLocations(oldSize, size); + } + } + } + + private void adjustLocations(Dimension oldSize, Dimension size) { + + int xOffset = (size.width - oldSize.width) / 2; + int yOffset = (size.height - oldSize.height) / 2; + + // now, move each vertex to be at the new screen center + while(true) { + try { + for(V v : getGraph().getVertices()) { + offsetVertex(v, xOffset, yOffset); + } + break; + } catch(ConcurrentModificationException cme) { + } + } + } + + public boolean isLocked(V v) { + return dontmove.contains(v); + } + + @SuppressWarnings("unchecked") + public void setInitializer(Transformer initializer) { + if(this.equals(initializer)) { + throw new IllegalArgumentException("Layout cannot be initialized with itself"); + } + Transformer chain = + ChainedTransformer.getInstance(initializer, CloneTransformer.getInstance()); + this.locations = LazyMap.decorate(new HashMap(), (Transformer)chain); + initialized = true; + } + + /** + * Returns the current size of the visualization space, accoring to the + * last call to resize(). + * + * @return the current size of the screen + */ + public Dimension getSize() { + return size; + } + + /** + * Returns the Coordinates object that stores the vertex' x and y location. + * + * @param v + * A Vertex that is a part of the Graph being visualized. + * @return A Coordinates object with x and y locations. + */ + private Point2D getCoordinates(V v) { + return locations.get(v); + } + + public Point2D transform(V v) { + return getCoordinates(v); + } + + /** + * Returns the x coordinate of the vertex from the Coordinates object. + * in most cases you will be better off calling transform(v). + */ + public double getX(V v) { + assert getCoordinates(v) != null : "Cannot getX for an unmapped vertex "+v; + return getCoordinates(v).getX(); + } + + /** + * Returns the y coordinate of the vertex from the Coordinates object. + * In most cases you will be better off calling transform(v). + */ + public double getY(V v) { + assert getCoordinates(v) != null : "Cannot getY for an unmapped vertex "+v; + return getCoordinates(v).getY(); + } + + /** + * @param v + * @param xOffset + * @param yOffset + */ + protected void offsetVertex(V v, double xOffset, double yOffset) { + Point2D c = getCoordinates(v); + c.setLocation(c.getX()+xOffset, c.getY()+yOffset); + setLocation(v, c); + } + + /** + * Accessor for the graph that represets all vertices. + * + * @return the graph that contains all vertices. + */ + public Graph getGraph() { + return graph; + } + + /** + * Forcibly moves a vertex to the (x,y) location by setting its x and y + * locations to the inputted location. Does not add the vertex to the + * "dontmove" list, and (in the default implementation) does not make any + * adjustments to the rest of the graph. + */ + public void setLocation(V picked, double x, double y) { + Point2D coord = getCoordinates(picked); + coord.setLocation(x, y); + } + + public void setLocation(V picked, Point2D p) { + Point2D coord = getCoordinates(picked); + coord.setLocation(p); + } + + /** + * Locks {@code v} in place if {@code state} is {@code true}, otherwise unlocks it. + */ + public void lock(V v, boolean state) { + if(state == true) + dontmove.add(v); + else + dontmove.remove(v); + } + + /** + * Locks all vertices in place if {@code lock} is {@code true}, otherwise unlocks all vertices. + */ + public void lock(boolean lock) { + for(V v : graph.getVertices()) { + lock(v, lock); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/AggregateLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/AggregateLayout.java new file mode 100644 index 0000000000..38058377a1 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/AggregateLayout.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * + * + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; + +/** + * A {@code Layout} implementation that combines + * multiple other layouts so that they may be manipulated + * as one layout. The relaxer thread will step each layout + * in sequence. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the vertex type + * @param the edge type + */ +public class AggregateLayout implements Layout, IterativeContext { + + protected Layout delegate; + protected Map,Point2D> layouts = new HashMap,Point2D>(); + + /** + * Creates an instance backed by the specified {@code delegate}. + * @param delegate + */ + public AggregateLayout(Layout delegate) { + this.delegate = delegate; + } + + /** + * @return the delegate + */ + public Layout getDelegate() { + return delegate; + } + + /** + * @param delegate the delegate to set + */ + public void setDelegate(Layout delegate) { + this.delegate = delegate; + } + + /** + * adds the passed layout as a sublayout, also specifying + * the center of where this sublayout should appear + * @param layout + * @param center + */ + public void put(Layout layout, Point2D center) { + layouts.put(layout,center); + } + + /** + * Returns the center of the passed layout. + * @param layout + * @return the center of the passed layout + */ + public Point2D get(Layout layout) { + return layouts.get(layout); + } + + /** + * Removes {@code layout} from this instance. + */ + public void remove(Layout layout) { + layouts.remove(layout); + } + + /** + * Removes all layouts from this instance. + */ + public void removeAll() { + layouts.clear(); + } + + /** + * Returns the graph for which this layout is defined. + * @return the graph for which this layout is defined + * @see edu.uci.ics.jung.algorithms.layout.Layout#getGraph() + */ + public Graph getGraph() { + return delegate.getGraph(); + } + + /** + * Returns the size of the underlying layout. + * @return the size of the underlying layout + * @see edu.uci.ics.jung.algorithms.layout.Layout#getSize() + */ + public Dimension getSize() { + return delegate.getSize(); + } + + /** + * + * @see edu.uci.ics.jung.algorithms.layout.Layout#initialize() + */ + public void initialize() { + delegate.initialize(); + for(Layout layout : layouts.keySet()) { + layout.initialize(); + } + } + + /** + * Override to test if the passed vertex is locked in + * any of the layouts. + * @param v + * @return true if v is locked in any of the layouts, and false otherwise + * @see edu.uci.ics.jung.algorithms.layout.Layout#isLocked(java.lang.Object) + */ + public boolean isLocked(V v) { + boolean locked = false; + for(Layout layout : layouts.keySet()) { + locked |= layout.isLocked(v); + } + locked |= delegate.isLocked(v); + return locked; + } + + /** + * override to lock or unlock this vertex in any layout with + * a subgraph containing it + * @param v + * @param state + * @see edu.uci.ics.jung.algorithms.layout.Layout#lock(java.lang.Object, boolean) + */ + public void lock(V v, boolean state) { + for(Layout layout : layouts.keySet()) { + if(layout.getGraph().getVertices().contains(v)) { + layout.lock(v, state); + } + } + delegate.lock(v, state); + } + + /** + * + * @see edu.uci.ics.jung.algorithms.layout.Layout#reset() + */ + public void reset() { + for(Layout layout : layouts.keySet()) { + layout.reset(); + } + delegate.reset(); + } + + /** + * @param graph + * @see edu.uci.ics.jung.algorithms.layout.Layout#setGraph(edu.uci.ics.jung.graph.Graph) + */ + public void setGraph(Graph graph) { + delegate.setGraph(graph); + } + + /** + * @param initializer + * @see edu.uci.ics.jung.algorithms.layout.Layout#setInitializer(org.apache.commons.collections15.Transformer) + */ + public void setInitializer(Transformer initializer) { + delegate.setInitializer(initializer); + } + + /** + * @param v + * @param location + * @see edu.uci.ics.jung.algorithms.layout.Layout#setLocation(java.lang.Object, java.awt.geom.Point2D) + */ + public void setLocation(V v, Point2D location) { + boolean wasInSublayout = false; + for(Layout layout : layouts.keySet()) { + if(layout.getGraph().getVertices().contains(v)) { + Point2D center = layouts.get(layout); + // transform by the layout itself, but offset to the + // center of the sublayout + Dimension d = layout.getSize(); + + AffineTransform at = + AffineTransform.getTranslateInstance(-center.getX()+d.width/2,-center.getY()+d.height/2); + Point2D localLocation = at.transform(location, null); + layout.setLocation(v, localLocation); + wasInSublayout = true; + } + } + if(wasInSublayout == false && getGraph().getVertices().contains(v)) { + delegate.setLocation(v, location); + } + } + + /** + * @param d + * @see edu.uci.ics.jung.algorithms.layout.Layout#setSize(java.awt.Dimension) + */ + public void setSize(Dimension d) { + delegate.setSize(d); + } + + /** + * Returns a map from each {@code Layout} instance to its center point. + */ + public Map,Point2D> getLayouts() { + return layouts; + } + + /** + * Returns the location of the vertex. The location is specified first + * by the sublayouts, and then by the base layout if no sublayouts operate + * on this vertex. + * @return the location of the vertex + * @see org.apache.commons.collections15.Transformer#transform(java.lang.Object) + */ + public Point2D transform(V v) { + boolean wasInSublayout = false; + for(Layout layout : layouts.keySet()) { + if(layout.getGraph().getVertices().contains(v)) { + wasInSublayout = true; + Point2D center = layouts.get(layout); + // transform by the layout itself, but offset to the + // center of the sublayout + Dimension d = layout.getSize(); + AffineTransform at = + AffineTransform.getTranslateInstance(center.getX()-d.width/2, + center.getY()-d.height/2); + return at.transform(layout.transform(v),null); + } + } + if(wasInSublayout == false) { + return delegate.transform(v); + } + return null; + + } + + /** + * Check all sublayouts.keySet() and the delegate layout, returning + * done == true iff all are done. + */ + public boolean done() { + boolean done = true; + for(Layout layout : layouts.keySet()) { + if(layout instanceof IterativeContext) { + done &= ((IterativeContext)layout).done(); + } + } + if(delegate instanceof IterativeContext) { + done &= ((IterativeContext)delegate).done(); + } + return done; + } + + /** + * call step on any sublayout that is also an IterativeContext + * and is not done + */ + public void step() { + for(Layout layout : layouts.keySet()) { + if(layout instanceof IterativeContext) { + IterativeContext context = (IterativeContext)layout; + if(context.done() == false) { + context.step(); + } + } + } + if(delegate instanceof IterativeContext) { + IterativeContext context = (IterativeContext)delegate; + if(context.done() == false) { + context.step(); + } + } + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/BalloonLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/BalloonLayout.java new file mode 100644 index 0000000000..1d9f384ae7 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/BalloonLayout.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2005, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * Created on Jul 9, 2005 + */ + +package edu.uci.ics.jung.algorithms.layout; +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.map.LazyMap; + +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.util.TreeUtils; + +/** + * A {@code Layout} implementation that assigns positions to {@code Tree} or + * {@code Forest} vertices using associations with nested circles ("balloons"). + * A balloon is nested inside another balloon if the first balloon's subtree + * is a subtree of the second balloon's subtree. + * + * @author Tom Nelson + * + */ +public class BalloonLayout extends TreeLayout { + + protected Map polarLocations = + LazyMap.decorate(new HashMap(), + new Transformer() { + public PolarPoint transform(V arg0) { + return new PolarPoint(); + }}); + + protected Map radii = new HashMap(); + + /** + * Creates an instance based on the input forest. + */ + public BalloonLayout(Forest g) + { + super(g); + } + + protected void setRootPolars() + { + List roots = TreeUtils.getRoots(graph); + if(roots.size() == 1) { + // its a Tree + V root = roots.get(0); + setRootPolar(root); + setPolars(new ArrayList(graph.getChildren(root)), + getCenter(), getSize().width/2); + } else if (roots.size() > 1) { + // its a Forest + setPolars(roots, getCenter(), getSize().width/2); + } + } + + protected void setRootPolar(V root) { + PolarPoint pp = new PolarPoint(0,0); + Point2D p = getCenter(); + polarLocations.put(root, pp); + locations.put(root, p); + } + + + protected void setPolars(List kids, Point2D parentLocation, double parentRadius) { + + int childCount = kids.size(); + if(childCount == 0) return; + // handle the 1-child case with 0 limit on angle. + double angle = Math.max(0, Math.PI / 2 * (1 - 2.0/childCount)); + double childRadius = parentRadius*Math.cos(angle) / (1 + Math.cos(angle)); + double radius = parentRadius - childRadius; + + double rand = Math.random(); + + for(int i=0; i< childCount; i++) { + V child = kids.get(i); + double theta = i* 2*Math.PI/childCount + rand; + radii.put(child, childRadius); + + PolarPoint pp = new PolarPoint(theta, radius); + polarLocations.put(child, pp); + + Point2D p = PolarPoint.polarToCartesian(pp); + p.setLocation(p.getX()+parentLocation.getX(), p.getY()+parentLocation.getY()); + locations.put(child, p); + setPolars(new ArrayList(graph.getChildren(child)), p, childRadius); + } + } + + @Override + public void setSize(Dimension size) { + this.size = size; + setRootPolars(); + } + + /** + * Returns the coordinates of {@code v}'s parent, or the + * center of this layout's area if it's a root. + */ + public Point2D getCenter(V v) { + V parent = graph.getParent(v); + if(parent == null) { + return getCenter(); + } + return locations.get(parent); + } + + @Override + public void setLocation(V v, Point2D location) { + Point2D c = getCenter(v); + Point2D pv = new Point2D.Double(location.getX()-c.getX(),location.getY()-c.getY()); + PolarPoint newLocation = PolarPoint.cartesianToPolar(pv); + polarLocations.get(v).setLocation(newLocation); + + Point2D center = getCenter(v); + pv.setLocation(pv.getX()+center.getX(), pv.getY()+center.getY()); + locations.put(v, pv); + } + + @Override + public Point2D transform(V v) { + return locations.get(v); + } + + /** + * @return the radii + */ + public Map getRadii() { + return radii; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/CircleLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/CircleLayout.java new file mode 100644 index 0000000000..8cafb77827 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/CircleLayout.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +/* + * Created on Dec 4, 2003 + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.map.LazyMap; + +import edu.uci.ics.jung.graph.Graph; + + + +/** + * A {@code Layout} implementation that positions vertices equally spaced on a regular circle. + * + * @author Masanori Harada + */ +public class CircleLayout extends AbstractLayout { + + private double radius; + private List vertex_ordered_list; + + Map circleVertexDataMap = + LazyMap.decorate(new HashMap(), + new Factory() { + public CircleVertexData create() { + return new CircleVertexData(); + }}); + + /** + * Creates an instance for the specified graph. + */ + public CircleLayout(Graph g) { + super(g); + } + + /** + * Returns the radius of the circle. + */ + public double getRadius() { + return radius; + } + + /** + * Sets the radius of the circle. Must be called before + * {@code initialize()} is called. + */ + public void setRadius(double radius) { + this.radius = radius; + } + + /** + * Sets the order of the vertices in the layout according to the ordering + * specified by {@code comparator}. + */ + public void setVertexOrder(Comparator comparator) + { + if (vertex_ordered_list == null) + vertex_ordered_list = new ArrayList(getGraph().getVertices()); + Collections.sort(vertex_ordered_list, comparator); + } + + /** + * Sets the order of the vertices in the layout according to the ordering + * of {@code vertex_list}. + */ + public void setVertexOrder(List vertex_list) + { + if (!vertex_list.containsAll(getGraph().getVertices())) + throw new IllegalArgumentException("Supplied list must include " + + "all vertices of the graph"); + this.vertex_ordered_list = vertex_list; + } + + public void reset() { + initialize(); + } + + public void initialize() + { + Dimension d = getSize(); + + if (d != null) + { + if (vertex_ordered_list == null) + setVertexOrder(new ArrayList(getGraph().getVertices())); + + double height = d.getHeight(); + double width = d.getWidth(); + + if (radius <= 0) { + radius = 0.45 * (height < width ? height : width); + } + + int i = 0; + for (V v : vertex_ordered_list) + { + Point2D coord = transform(v); + + double angle = (2 * Math.PI * i) / vertex_ordered_list.size(); + + coord.setLocation(Math.cos(angle) * radius + width / 2, + Math.sin(angle) * radius + height / 2); + + CircleVertexData data = getCircleData(v); + data.setAngle(angle); + i++; + } + } + } + + protected CircleVertexData getCircleData(V v) { + return circleVertexDataMap.get(v); + } + + protected static class CircleVertexData { + private double angle; + + protected double getAngle() { + return angle; + } + + protected void setAngle(double angle) { + this.angle = angle; + } + + @Override + public String toString() { + return "CircleVertexData: angle=" + angle; + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/DAGLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/DAGLayout.java new file mode 100644 index 0000000000..97d3ee6b55 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/DAGLayout.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * + * Created on Dec 4, 2003 + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of {@code Layout} suitable for tree-like directed + * acyclic graphs. Parts of it will probably not terminate if the graph is + * cyclic! The layout will result in directed edges pointing generally upwards. + * Any vertices with no successors are considered to be level 0, and tend + * towards the top of the layout. Any vertex has a level one greater than the + * maximum level of all its successors. + * + * + * @author John Yesberg + */ +public class DAGLayout extends SpringLayout { + + /** + * Each vertex has a minimumLevel. Any vertex with no successors has + * minimumLevel of zero. The minimumLevel of any vertex must be strictly + * greater than the minimumLevel of its parents. (Vertex A is a parent of + * Vertex B iff there is an edge from B to A.) Typically, a vertex will + * have a minimumLevel which is one greater than the minimumLevel of its + * parent's. However, if the vertex has two parents, its minimumLevel will + * be one greater than the maximum of the parents'. We need to calculate + * the minimumLevel for each vertex. When we layout the graph, vertices + * cannot be drawn any higher than the minimumLevel. The graphHeight of a + * graph is the greatest minimumLevel that is used. We will modify the + * SpringLayout calculations so that nodes cannot move above their assigned + * minimumLevel. + */ + private Map minLevels = new HashMap(); + // Simpler than the "pair" technique. + static int graphHeight; + static int numRoots; + final double SPACEFACTOR = 1.3; + // How much space do we allow for additional floating at the bottom. + final double LEVELATTRACTIONRATE = 0.8; + + /** + * A bunch of parameters to help work out when to stop quivering. + * + * If the MeanSquareVel(ocity) ever gets below the MSV_THRESHOLD, then we + * will start a final cool-down phase of COOL_DOWN_INCREMENT increments. If + * the MeanSquareVel ever exceeds the threshold, we will exit the cool down + * phase, and continue looking for another opportunity. + */ + final double MSV_THRESHOLD = 10.0; + double meanSquareVel; + boolean stoppingIncrements = false; + int incrementsLeft; + final int COOL_DOWN_INCREMENTS = 200; + + /** + * Creates an instance for the specified graph. + */ + public DAGLayout(Graph g) { + super(g); + } + + /** + * setRoot calculates the level of each vertex in the graph. Level 0 is + * allocated to any vertex with no successors. Level n+1 is allocated to + * any vertex whose successors' maximum level is n. + */ + public void setRoot(Graph g) { + numRoots = 0; + for(V v : g.getVertices()) { + Collection successors = getGraph().getSuccessors(v); + if (successors.size() == 0) { + setRoot(v); + numRoots++; + } + } + } + + /** + * Set vertex v to be level 0. + */ + public void setRoot(V v) { + minLevels.put(v, new Integer(0)); + // set all the levels. + propagateMinimumLevel(v); + } + + /** + * A recursive method for allocating the level for each vertex. Ensures + * that all predecessors of v have a level which is at least one greater + * than the level of v. + * + * @param v + */ + public void propagateMinimumLevel(V v) { + int level = minLevels.get(v).intValue(); + for(V child : getGraph().getPredecessors(v)) { + int oldLevel, newLevel; + Number o = minLevels.get(child); + if (o != null) + oldLevel = o.intValue(); + else + oldLevel = 0; + newLevel = Math.max(oldLevel, level + 1); + minLevels.put(child, new Integer(newLevel)); + + if (newLevel > graphHeight) + graphHeight = newLevel; + propagateMinimumLevel(child); + } + } + + /** + * Sets random locations for a vertex within the dimensions of the space. + * This overrides the method in AbstractLayout + * + * @param coord + * @param d + */ + private void initializeLocation( + V v, + Point2D coord, + Dimension d) { + + int level = minLevels.get(v).intValue(); + int minY = (int) (level * d.getHeight() / (graphHeight * SPACEFACTOR)); + double x = Math.random() * d.getWidth(); + double y = Math.random() * (d.getHeight() - minY) + minY; + coord.setLocation(x,y); + } + + @Override + public void setSize(Dimension size) { + super.setSize(size); + for(V v : getGraph().getVertices()) { + initializeLocation(v,transform(v),getSize()); + } + } + + /** + * Had to override this one as well, to ensure that setRoot() is called. + */ + @Override + public void initialize() { + super.initialize(); + setRoot(getGraph()); + } + + /** + * Override the moveNodes() method from SpringLayout. The only change we + * need to make is to make sure that nodes don't float higher than the minY + * coordinate, as calculated by their minimumLevel. + */ + @Override + protected void moveNodes() { + // Dimension d = currentSize; + double oldMSV = meanSquareVel; + meanSquareVel = 0; + + synchronized (getSize()) { + + for(V v : getGraph().getVertices()) { + if (isLocked(v)) + continue; + SpringLayout.SpringVertexData vd = springVertexData.get(v); + Point2D xyd = transform(v); + + int width = getSize().width; + int height = getSize().height; + + // (JY addition: three lines are new) + int level = + minLevels.get(v).intValue(); + int minY = (int) (level * height / (graphHeight * SPACEFACTOR)); + int maxY = + level == 0 + ? (int) (height / (graphHeight * SPACEFACTOR * 2)) + : height; + + // JY added 2* - double the sideways repulsion. + vd.dx += 2 * vd.repulsiondx + vd.edgedx; + vd.dy += vd.repulsiondy + vd.edgedy; + + // JY Addition: Attract the vertex towards it's minimumLevel + // height. + double delta = xyd.getY() - minY; + vd.dy -= delta * LEVELATTRACTIONRATE; + if (level == 0) + vd.dy -= delta * LEVELATTRACTIONRATE; + // twice as much at the top. + + // JY addition: + meanSquareVel += (vd.dx * vd.dx + vd.dy * vd.dy); + + // keeps nodes from moving any faster than 5 per time unit + xyd.setLocation(xyd.getX()+Math.max(-5, Math.min(5, vd.dx)) , xyd.getY()+Math.max(-5, Math.min(5, vd.dy)) ); + + if (xyd.getX() < 0) { + xyd.setLocation(0, xyd.getY()); + } else if (xyd.getX() > width) { + xyd.setLocation(width, xyd.getY()); + } + + // (JY addition: These two lines replaced 0 with minY) + if (xyd.getY() < minY) { + xyd.setLocation(xyd.getX(), minY); + // (JY addition: replace height with maxY) + } else if (xyd.getY() > maxY) { + xyd.setLocation(xyd.getX(), maxY); + } + + // (JY addition: if there's only one root, anchor it in the + // middle-top of the screen) + if (numRoots == 1 && level == 0) { + xyd.setLocation(width/2, xyd.getY()); + } + } + } + //System.out.println("MeanSquareAccel="+meanSquareVel); + if (!stoppingIncrements + && Math.abs(meanSquareVel - oldMSV) < MSV_THRESHOLD) { + stoppingIncrements = true; + incrementsLeft = COOL_DOWN_INCREMENTS; + } else if ( + stoppingIncrements + && Math.abs(meanSquareVel - oldMSV) <= MSV_THRESHOLD) { + incrementsLeft--; + if (incrementsLeft <= 0) + incrementsLeft = 0; + } + } + + /** + * Override incrementsAreDone so that we can eventually stop. + */ + @Override + public boolean done() { + if (stoppingIncrements && incrementsLeft == 0) + return true; + else + return false; + } + + /** + * Override forceMove so that if someone moves a node, we can re-layout + * everything. + */ + @Override + public void setLocation(V picked, double x, double y) { + Point2D coord = transform(picked); + coord.setLocation(x,y); + stoppingIncrements = false; + } + + /** + * Override forceMove so that if someone moves a node, we can re-layout + * everything. + */ + @Override + public void setLocation(V picked, Point2D p) { + Point2D coord = transform(picked); + coord.setLocation(p); + stoppingIncrements = false; + } + + /** + * Overridden relaxEdges. This one reduces the effect of edges between + * greatly different levels. + * + */ + @Override + protected void relaxEdges() { + for(E e : getGraph().getEdges()) { + Pair endpoints = getGraph().getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + Point2D p1 = transform(v1); + Point2D p2 = transform(v2); + double vx = p1.getX() - p2.getX(); + double vy = p1.getY() - p2.getY(); + double len = Math.sqrt(vx * vx + vy * vy); + + // JY addition. + int level1 = + minLevels.get(v1).intValue(); + int level2 = + minLevels.get(v2).intValue(); + + // desiredLen *= Math.pow( 1.1, (v1.degree() + v2.degree()) ); +// double desiredLen = getLength(e); + double desiredLen = lengthFunction.transform(e); + + // round from zero, if needed [zero would be Bad.]. + len = (len == 0) ? .0001 : len; + + // force factor: optimal length minus actual length, + // is made smaller as the current actual length gets larger. + // why? + + // System.out.println("Desired : " + getLength( e )); + double f = force_multiplier * (desiredLen - len) / len; + + f = f * Math.pow(stretch / 100.0, + (getGraph().degree(v1) + getGraph().degree(v2) -2)); + + // JY addition. If this is an edge which stretches a long way, + // don't be so concerned about it. + if (level1 != level2) + f = f / Math.pow(Math.abs(level2 - level1), 1.5); + + // f= Math.min( 0, f ); + + // the actual movement distance 'dx' is the force multiplied by the + // distance to go. + double dx = f * vx; + double dy = f * vy; + SpringVertexData v1D, v2D; + v1D = springVertexData.get(v1); + v2D = springVertexData.get(v2); + +// SpringEdgeData sed = getSpringEdgeData(e); +// sed.f = f; + + v1D.edgedx += dx; + v1D.edgedy += dy; + v2D.edgedx += -dx; + v2D.edgedy += -dy; + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout.java new file mode 100644 index 0000000000..c8a2a24a8a --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout.java @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.map.LazyMap; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Map; + +/** + * Implements the Fruchterman-Reingold force-directed algorithm for node layout. + * + *

      Behavior is determined by the following settable parameters: + *

        + *
      • attraction multiplier: how much edges try to keep their vertices together + *
      • repulsion multiplier: how much vertices try to push each other apart + *
      • maximum iterations: how many iterations this algorithm will use before stopping + *
      + * Each of the first two defaults to 0.75; the maximum number of iterations defaults to 700. + * + * @see "Fruchterman and Reingold, 'Graph Drawing by Force-directed Placement'" + * @see "http://i11www.ilkd.uni-karlsruhe.de/teaching/SS_04/visualisierung/papers/fruchterman91graph.pdf" + * @author Scott White, Yan-Biao Boey, Danyel Fisher + */ +public class FRLayout extends AbstractLayout implements IterativeContext { + + private double forceConstant; + + private double temperature; + + private int currentIteration; + + private int mMaxIterations = 700; + + private Map frVertexData = + LazyMap.decorate(new HashMap(), new Factory() { + public FRVertexData create() { + return new FRVertexData(); + }}); + + private double attraction_multiplier = 0.75; + + private double attraction_constant; + + private double repulsion_multiplier = 0.75; + + private double repulsion_constant; + + private double max_dimension; + + /** + * Creates an instance for the specified graph. + */ + public FRLayout(Graph g) { + super(g); + } + + /** + * Creates an instance of size {@code d} for the specified graph. + */ + public FRLayout(Graph g, Dimension d) { + super(g, new RandomLocationTransformer(d), d); + initialize(); + max_dimension = Math.max(d.height, d.width); + } + + @Override + public void setSize(Dimension size) { + if(initialized == false) { + setInitializer(new RandomLocationTransformer(size)); + } + super.setSize(size); + max_dimension = Math.max(size.height, size.width); + } + + /** + * Sets the attraction multiplier. + */ + public void setAttractionMultiplier(double attraction) { + this.attraction_multiplier = attraction; + } + + /** + * Sets the repulsion multiplier. + */ + public void setRepulsionMultiplier(double repulsion) { + this.repulsion_multiplier = repulsion; + } + + public void reset() { + doInit(); + } + + public void initialize() { + doInit(); + } + + private void doInit() { + Graph graph = getGraph(); + Dimension d = getSize(); + if(graph != null && d != null) { + currentIteration = 0; + temperature = d.getWidth() / 10; + + forceConstant = + Math + .sqrt(d.getHeight() + * d.getWidth() + / graph.getVertexCount()); + + attraction_constant = attraction_multiplier * forceConstant; + repulsion_constant = repulsion_multiplier * forceConstant; + } + } + + private double EPSILON = 0.000001D; + + /** + * Moves the iteration forward one notch, calculation attraction and + * repulsion between vertices and edges and cooling the temperature. + */ + public synchronized void step() { + currentIteration++; + + /** + * Calculate repulsion + */ + while(true) { + + try { + for(V v1 : getGraph().getVertices()) { + calcRepulsion(v1); + } + break; + } catch(ConcurrentModificationException cme) {} + } + + /** + * Calculate attraction + */ + while(true) { + try { + for(E e : getGraph().getEdges()) { + + calcAttraction(e); + } + break; + } catch(ConcurrentModificationException cme) {} + } + + + while(true) { + try { + for(V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + calcPositions(v); + } + break; + } catch(ConcurrentModificationException cme) {} + } + cool(); + } + + protected synchronized void calcPositions(V v) { + FRVertexData fvd = getFRData(v); + if(fvd == null) return; + Point2D xyd = transform(v); + double deltaLength = Math.max(EPSILON, fvd.norm()); + + double newXDisp = fvd.getX() / deltaLength + * Math.min(deltaLength, temperature); + + if (Double.isNaN(newXDisp)) { + throw new IllegalArgumentException( + "Unexpected mathematical result in FRLayout:calcPositions [xdisp]"); } + + double newYDisp = fvd.getY() / deltaLength + * Math.min(deltaLength, temperature); + xyd.setLocation(xyd.getX()+newXDisp, xyd.getY()+newYDisp); + + double borderWidth = getSize().getWidth() / 50.0; + double newXPos = xyd.getX(); + if (newXPos < borderWidth) { + newXPos = borderWidth + Math.random() * borderWidth * 2.0; + } else if (newXPos > (getSize().getWidth() - borderWidth)) { + newXPos = getSize().getWidth() - borderWidth - Math.random() + * borderWidth * 2.0; + } + + double newYPos = xyd.getY(); + if (newYPos < borderWidth) { + newYPos = borderWidth + Math.random() * borderWidth * 2.0; + } else if (newYPos > (getSize().getHeight() - borderWidth)) { + newYPos = getSize().getHeight() - borderWidth + - Math.random() * borderWidth * 2.0; + } + + xyd.setLocation(newXPos, newYPos); + } + + protected void calcAttraction(E e) { + Pair endpoints = getGraph().getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + boolean v1_locked = isLocked(v1); + boolean v2_locked = isLocked(v2); + + if(v1_locked && v2_locked) { + // both locked, do nothing + return; + } + Point2D p1 = transform(v1); + Point2D p2 = transform(v2); + if(p1 == null || p2 == null) return; + double xDelta = p1.getX() - p2.getX(); + double yDelta = p1.getY() - p2.getY(); + + double deltaLength = Math.max(EPSILON, Math.sqrt((xDelta * xDelta) + + (yDelta * yDelta))); + + double force = (deltaLength * deltaLength) / attraction_constant; + + if (Double.isNaN(force)) { throw new IllegalArgumentException( + "Unexpected mathematical result in FRLayout:calcPositions [force]"); } + + double dx = (xDelta / deltaLength) * force; + double dy = (yDelta / deltaLength) * force; + if(v1_locked == false) { + FRVertexData fvd1 = getFRData(v1); + fvd1.offset(-dx, -dy); + } + if(v2_locked == false) { + FRVertexData fvd2 = getFRData(v2); + fvd2.offset(dx, dy); + } + } + + protected void calcRepulsion(V v1) { + FRVertexData fvd1 = getFRData(v1); + if(fvd1 == null) + return; + fvd1.setLocation(0, 0); + + try { + for(V v2 : getGraph().getVertices()) { + +// if (isLocked(v2)) continue; + if (v1 != v2) { + Point2D p1 = transform(v1); + Point2D p2 = transform(v2); + if(p1 == null || p2 == null) continue; + double xDelta = p1.getX() - p2.getX(); + double yDelta = p1.getY() - p2.getY(); + + double deltaLength = Math.max(EPSILON, Math + .sqrt((xDelta * xDelta) + (yDelta * yDelta))); + + double force = (repulsion_constant * repulsion_constant) / deltaLength; + + if (Double.isNaN(force)) { throw new RuntimeException( + "Unexpected mathematical result in FRLayout:calcPositions [repulsion]"); } + + fvd1.offset((xDelta / deltaLength) * force, + (yDelta / deltaLength) * force); + } + } + } catch(ConcurrentModificationException cme) { + calcRepulsion(v1); + } + } + + private void cool() { + temperature *= (1.0 - currentIteration / (double) mMaxIterations); + } + + /** + * Sets the maximum number of iterations. + */ + public void setMaxIterations(int maxIterations) { + mMaxIterations = maxIterations; + } + + protected FRVertexData getFRData(V v) { + return frVertexData.get(v); + } + + /** + * This one is an incremental visualization. + */ + public boolean isIncremental() { + return true; + } + + /** + * Returns true once the current iteration has passed the maximum count, + * MAX_ITERATIONS. + */ + public boolean done() { + if (currentIteration > mMaxIterations || temperature < 1.0/max_dimension) + { + return true; + } + return false; + } + + protected static class FRVertexData extends Point2D.Double + { + protected void offset(double x, double y) + { + this.x += x; + this.y += y; + } + + protected double norm() + { + return Math.sqrt(x*x + y*y); + } + } +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout2.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout2.java new file mode 100644 index 0000000000..0f5b05ea85 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout2.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.map.LazyMap; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Implements the Fruchterman-Reingold force-directed algorithm for node layout. + * This is an experimental attempt at optimizing {@code FRLayout}; if it is successful + * it will be folded back into {@code FRLayout} (and this class will disappear). + * + *

      Behavior is determined by the following settable parameters: + *

        + *
      • attraction multiplier: how much edges try to keep their vertices together + *
      • repulsion multiplier: how much vertices try to push each other apart + *
      • maximum iterations: how many iterations this algorithm will use before stopping + *
      + * Each of the first two defaults to 0.75; the maximum number of iterations defaults to 700. + + * + * @see "Fruchterman and Reingold, 'Graph Drawing by Force-directed Placement'" + * @see http://i11www.ilkd.uni-karlsruhe.de/teaching/SS_04/visualisierung/papers/fruchterman91graph.pdf + * + * @author Tom Nelson + * @author Scott White, Yan-Biao Boey, Danyel Fisher + */ +public class FRLayout2 extends AbstractLayout implements IterativeContext { + + private double forceConstant; + + private double temperature; + + private int currentIteration; + + private int maxIterations = 700; + + private Map frVertexData = + LazyMap.decorate(new HashMap(), new Factory() { + public Point2D create() { + return new Point2D.Double(); + }}); + + private double attraction_multiplier = 0.75; + + private double attraction_constant; + + private double repulsion_multiplier = 0.75; + + private double repulsion_constant; + + private double max_dimension; + + private Rectangle2D innerBounds = new Rectangle2D.Double(); + + private boolean checked = false; + + /** + * Creates an instance for the specified graph. + */ + public FRLayout2(Graph g) { + super(g); + } + + /** + * Creates an instance of size {@code d} for the specified graph. + */ + public FRLayout2(Graph g, Dimension d) { + super(g, new RandomLocationTransformer(d), d); + max_dimension = Math.max(d.height, d.width); + initialize(); + } + + @Override + public void setSize(Dimension size) { + if(initialized == false) + setInitializer(new RandomLocationTransformer(size)); + super.setSize(size); + double t = size.width/50.0; + innerBounds.setFrameFromDiagonal(t,t,size.width-t,size.height-t); + max_dimension = Math.max(size.height, size.width); + } + + /** + * Sets the attraction multiplier. + */ + public void setAttractionMultiplier(double attraction) { + this.attraction_multiplier = attraction; + } + + /** + * Sets the repulsion multiplier. + */ + public void setRepulsionMultiplier(double repulsion) { + this.repulsion_multiplier = repulsion; + } + + public void reset() { + doInit(); + } + + public void initialize() { + doInit(); + } + + private void doInit() { + Graph graph = getGraph(); + Dimension d = getSize(); + if(graph != null && d != null) { + currentIteration = 0; + temperature = d.getWidth() / 10; + + forceConstant = + Math + .sqrt(d.getHeight() + * d.getWidth() + / graph.getVertexCount()); + + attraction_constant = attraction_multiplier * forceConstant; + repulsion_constant = repulsion_multiplier * forceConstant; + } + } + + private double EPSILON = 0.000001D; + + /** + * Moves the iteration forward one notch, calculation attraction and + * repulsion between vertices and edges and cooling the temperature. + */ + public synchronized void step() { + currentIteration++; + + /** + * Calculate repulsion + */ + while(true) { + + try { + for(V v1 : getGraph().getVertices()) { + calcRepulsion(v1); + } + break; + } catch(ConcurrentModificationException cme) {} + } + + /** + * Calculate attraction + */ + while(true) { + try { + for(E e : getGraph().getEdges()) { + calcAttraction(e); + } + break; + } catch(ConcurrentModificationException cme) {} + } + + + while(true) { + try { + for(V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + calcPositions(v); + } + break; + } catch(ConcurrentModificationException cme) {} + } + cool(); + } + + protected synchronized void calcPositions(V v) { + Point2D fvd = this.frVertexData.get(v); + if(fvd == null) return; + Point2D xyd = transform(v); + double deltaLength = Math.max(EPSILON, + Math.sqrt(fvd.getX()*fvd.getX()+fvd.getY()*fvd.getY())); + + double newXDisp = fvd.getX() / deltaLength + * Math.min(deltaLength, temperature); + + assert Double.isNaN(newXDisp) == false : "Unexpected mathematical result in FRLayout:calcPositions [xdisp]"; + + double newYDisp = fvd.getY() / deltaLength + * Math.min(deltaLength, temperature); + double newX = xyd.getX()+Math.max(-5, Math.min(5,newXDisp)); + double newY = xyd.getY()+Math.max(-5, Math.min(5,newYDisp)); + + newX = Math.max(innerBounds.getMinX(), Math.min(newX, innerBounds.getMaxX())); + newY = Math.max(innerBounds.getMinY(), Math.min(newY, innerBounds.getMaxY())); + + xyd.setLocation(newX, newY); + + } + + protected void calcAttraction(E e) { + Pair endpoints = getGraph().getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + boolean v1_locked = isLocked(v1); + boolean v2_locked = isLocked(v2); + + if(v1_locked && v2_locked) { + // both locked, do nothing + return; + } + Point2D p1 = transform(v1); + Point2D p2 = transform(v2); + if(p1 == null || p2 == null) return; + double xDelta = p1.getX() - p2.getX(); + double yDelta = p1.getY() - p2.getY(); + + double deltaLength = Math.max(EPSILON, p1.distance(p2)); + + double force = deltaLength / attraction_constant; + + assert Double.isNaN(force) == false : "Unexpected mathematical result in FRLayout:calcPositions [force]"; + + double dx = xDelta * force; + double dy = yDelta * force; + Point2D fvd1 = frVertexData.get(v1); + Point2D fvd2 = frVertexData.get(v2); + if(v2_locked) { + // double the offset for v1, as v2 will not be moving in + // the opposite direction + fvd1.setLocation(fvd1.getX()-2*dx, fvd1.getY()-2*dy); + } else { + fvd1.setLocation(fvd1.getX()-dx, fvd1.getY()-dy); + } + if(v1_locked) { + // double the offset for v2, as v1 will not be moving in + // the opposite direction + fvd2.setLocation(fvd2.getX()+2*dx, fvd2.getY()+2*dy); + } else { + fvd2.setLocation(fvd2.getX()+dx, fvd2.getY()+dy); + } + } + + protected void calcRepulsion(V v1) { + Point2D fvd1 = frVertexData.get(v1); + if(fvd1 == null) return; + fvd1.setLocation(0, 0); + boolean v1_locked = isLocked(v1); + + try { + for(V v2 : getGraph().getVertices()) { + + boolean v2_locked = isLocked(v2); + if (v1_locked && v2_locked) continue; + if (v1 != v2) { + Point2D p1 = transform(v1); + Point2D p2 = transform(v2); + if(p1 == null || p2 == null) continue; + double xDelta = p1.getX() - p2.getX(); + double yDelta = p1.getY() - p2.getY(); + + double deltaLength = Math.max(EPSILON, p1.distanceSq(p2)); + + double force = (repulsion_constant * repulsion_constant);// / deltaLength; + + double forceOverDeltaLength = force / deltaLength; + + assert Double.isNaN(force) == false : "Unexpected mathematical result in FRLayout:calcPositions [repulsion]"; + + if(v2_locked) { + // double the offset for v1, as v2 will not be moving in + // the opposite direction + fvd1.setLocation(fvd1.getX()+2 * xDelta * forceOverDeltaLength, + fvd1.getY()+ 2 * yDelta * forceOverDeltaLength); + } else { + fvd1.setLocation(fvd1.getX()+xDelta * forceOverDeltaLength, + fvd1.getY()+yDelta * forceOverDeltaLength); + } + } + } + } catch(ConcurrentModificationException cme) { + calcRepulsion(v1); + } + } + + private void cool() { + temperature *= (1.0 - currentIteration / (double) maxIterations); + } + + /** + * Sets the maximum number of iterations. + */ + public void setMaxIterations(int maxIterations) { + this.maxIterations = maxIterations; + } + + /** + * This one is an incremental visualization. + */ + public boolean isIncremental() { + return true; + } + + /** + * Returns true once the current iteration has passed the maximum count, + * MAX_ITERATIONS. + */ + public boolean done() { + if (currentIteration > maxIterations || temperature < 1.0/max_dimension) { + if (!checked) + { +// System.out.println("current iteration: " + currentIteration); +// System.out.println("temperature: " + temperature); + checked = true; + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/GraphElementAccessor.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/GraphElementAccessor.java new file mode 100644 index 0000000000..4cf1c51c92 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/GraphElementAccessor.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2005, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * + * Created on Apr 12, 2005 + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Shape; +import java.util.Collection; + +/** + * Interface for coordinate-based selection of graph components. + * @author Tom Nelson + * @author Joshua O'Madadhain + */ +public interface GraphElementAccessor +{ + /** + * Returns a vertex which is associated with the + * location (x,y). This is typically determined + * with respect to the vertex's location as specified + * by a Layout. + */ + V getVertex(Layout layout, double x, double y); + + /** + * Returns the vertices contained within {@code rectangle} relative + * to {@code layout}. + */ + Collection getVertices(Layout layout, Shape rectangle); + + /** + * Returns an edge which is associated with the + * location (x,y). This is typically determined + * with respect to the edge's location as specified + * by a {@code Layout}. + */ + E getEdge(Layout layout, double x, double y); + +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/ISOMLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/ISOMLayout.java new file mode 100644 index 0000000000..bea8edaa46 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/ISOMLayout.java @@ -0,0 +1,231 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.layout; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.map.LazyMap; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Implements a self-organizing map layout algorithm, based on Meyer's + * self-organizing graph methods. + * + * @author Yan Biao Boey + */ +public class ISOMLayout extends AbstractLayout implements IterativeContext { + + Map isomVertexData = + LazyMap.decorate(new HashMap(), + new Factory() { + public ISOMVertexData create() { + return new ISOMVertexData(); + }}); + + private int maxEpoch; + private int epoch; + + private int radiusConstantTime; + private int radius; + private int minRadius; + + private double adaption; + private double initialAdaption; + private double minAdaption; + + protected GraphElementAccessor elementAccessor = + new RadiusGraphElementAccessor(); + + private double coolingFactor; + + private List queue = new ArrayList(); + private String status = null; + + /** + * Returns the current number of epochs and execution status, as a string. + */ + public String getStatus() { + return status; + } + + /** + * Creates an ISOMLayout instance for the specified graph g. + * @param g + */ + public ISOMLayout(Graph g) { + super(g); + } + + public void initialize() { + + setInitializer(new RandomLocationTransformer(getSize())); + maxEpoch = 2000; + epoch = 1; + + radiusConstantTime = 100; + radius = 5; + minRadius = 1; + + initialAdaption = 90.0D / 100.0D; + adaption = initialAdaption; + minAdaption = 0; + + //factor = 0; //Will be set later on + coolingFactor = 2; + + //temperature = 0.03; + //initialJumpRadius = 100; + //jumpRadius = initialJumpRadius; + + //delay = 100; + } + + + /** + * Advances the current positions of the graph elements. + */ + public void step() { + status = "epoch: " + epoch + "; "; + if (epoch < maxEpoch) { + adjust(); + updateParameters(); + status += " status: running"; + + } else { + status += "adaption: " + adaption + "; "; + status += "status: done"; +// done = true; + } + } + + private synchronized void adjust() { + //Generate random position in graph space + Point2D tempXYD = new Point2D.Double(); + + // creates a new XY data location + tempXYD.setLocation(10 + Math.random() * getSize().getWidth(), + 10 + Math.random() * getSize().getHeight()); + + //Get closest vertex to random position + V winner = elementAccessor.getVertex(this, tempXYD.getX(), tempXYD.getY()); + + while(true) { + try { + for(V v : getGraph().getVertices()) { + ISOMVertexData ivd = getISOMVertexData(v); + ivd.distance = 0; + ivd.visited = false; + } + break; + } catch(ConcurrentModificationException cme) {} + } + adjustVertex(winner, tempXYD); + } + + private synchronized void updateParameters() { + epoch++; + double factor = Math.exp(-1 * coolingFactor * (1.0 * epoch / maxEpoch)); + adaption = Math.max(minAdaption, factor * initialAdaption); + //jumpRadius = (int) factor * jumpRadius; + //temperature = factor * temperature; + if ((radius > minRadius) && (epoch % radiusConstantTime == 0)) { + radius--; + } + } + + private synchronized void adjustVertex(V v, Point2D tempXYD) { + queue.clear(); + ISOMVertexData ivd = getISOMVertexData(v); + ivd.distance = 0; + ivd.visited = true; + queue.add(v); + V current; + + while (!queue.isEmpty()) { + current = queue.remove(0); + ISOMVertexData currData = getISOMVertexData(current); + Point2D currXYData = transform(current); + + double dx = tempXYD.getX() - currXYData.getX(); + double dy = tempXYD.getY() - currXYData.getY(); + double factor = adaption / Math.pow(2, currData.distance); + + currXYData.setLocation(currXYData.getX()+(factor*dx), currXYData.getY()+(factor*dy)); + + if (currData.distance < radius) { + Collection s = getGraph().getNeighbors(current); + while(true) { + try { + for(V child : s) { + ISOMVertexData childData = getISOMVertexData(child); + if (childData != null && !childData.visited) { + childData.visited = true; + childData.distance = currData.distance + 1; + queue.add(child); + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + } + } + } + + protected ISOMVertexData getISOMVertexData(V v) { + return isomVertexData.get(v); + } + + /** + * This one is an incremental visualization. + * @return true is the layout algorithm is incremental, false otherwise + */ + public boolean isIncremental() { + return true; + } + + /** + * Returns true if the vertex positions are no longer being + * updated. Currently ISOMLayout stops updating vertex + * positions after a certain number of iterations have taken place. + * @return true if the vertex position updates have stopped, + * false otherwise + */ + public boolean done() { + return epoch >= maxEpoch; + } + + protected static class ISOMVertexData { + int distance; + boolean visited; + + protected ISOMVertexData() { + distance = 0; + visited = false; + } + } + + /** + * Resets the layout iteration count to 0, which allows the layout algorithm to + * continue updating vertex positions. + */ + public void reset() { + epoch = 0; + } +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/KKLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/KKLayout.java new file mode 100644 index 0000000000..a1b9f40293 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/KKLayout.java @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.layout; +/* + * This source is under the same license with JUNG. + * http://jung.sourceforge.net/license.txt for a description. + */ + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.shortestpath.Distance; +import edu.uci.ics.jung.algorithms.shortestpath.DistanceStatistics; +import edu.uci.ics.jung.algorithms.shortestpath.UnweightedShortestPath; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; + +/** + * Implements the Kamada-Kawai algorithm for node layout. + * Does not respect filter calls, and sometimes crashes when the view changes to it. + * + * @see "Tomihisa Kamada and Satoru Kawai: An algorithm for drawing general indirect graphs. Information Processing Letters 31(1):7-15, 1989" + * @see "Tomihisa Kamada: On visualization of abstract objects and relations. Ph.D. dissertation, Dept. of Information Science, Univ. of Tokyo, Dec. 1988." + * + * @author Masanori Harada + */ +public class KKLayout extends AbstractLayout implements IterativeContext { + + private double EPSILON = 0.1d; + + private int currentIteration; + private int maxIterations = 2000; + private String status = "KKLayout"; + + private double L; // the ideal length of an edge + private double K = 1; // arbitrary const number + private double[][] dm; // distance matrix + + private boolean adjustForGravity = true; + private boolean exchangeVertices = true; + + private V[] vertices; + private Point2D[] xydata; + + /** + * Retrieves graph distances between vertices of the visible graph + */ + protected Distance distance; + + /** + * The diameter of the visible graph. In other words, the maximum over all pairs + * of vertices of the length of the shortest path between a and bf the visible graph. + */ + protected double diameter; + + /** + * A multiplicative factor which partly specifies the "preferred" length of an edge (L). + */ + private double length_factor = 0.9; + + /** + * A multiplicative factor which specifies the fraction of the graph's diameter to be + * used as the inter-vertex distance between disconnected vertices. + */ + private double disconnected_multiplier = 0.5; + + /** + * Creates an instance for the specified graph. + */ + public KKLayout(Graph g) + { + this(g, new UnweightedShortestPath(g)); + } + + /** + * Creates an instance for the specified graph and distance metric. + */ + public KKLayout(Graph g, Distance distance){ + super(g); + this.distance = distance; + } + + /** + * Sets a multiplicative factor which + * partly specifies the "preferred" length of an edge (L). + */ + public void setLengthFactor(double length_factor){ + this.length_factor = length_factor; + } + + /** + * Sets a multiplicative factor that specifies the fraction of the graph's diameter to be + * used as the inter-vertex distance between disconnected vertices. + */ + public void setDisconnectedDistanceMultiplier(double disconnected_multiplier){ + this.disconnected_multiplier = disconnected_multiplier; + } + + /** + * Returns a string with information about the current status of the algorithm. + */ + public String getStatus() { + return status + this.getSize(); + } + + /** + * Sets the maximum number of iterations. + */ + public void setMaxIterations(int maxIterations) { + this.maxIterations = maxIterations; + } + + /** + * This one is an incremental visualization. + */ + public boolean isIncremental() { + return true; + } + + /** + * Returns true once the current iteration has passed the maximum count. + */ + public boolean done() { + if (currentIteration > maxIterations) { + return true; + } + return false; + } + + @SuppressWarnings("unchecked") + public void initialize() { + currentIteration = 0; + + if(graph != null && size != null) { + + double height = size.getHeight(); + double width = size.getWidth(); + + int n = graph.getVertexCount(); + dm = new double[n][n]; + vertices = (V[])graph.getVertices().toArray(); + xydata = new Point2D[n]; + + // assign IDs to all visible vertices + while(true) { + try { + int index = 0; + for(V v : graph.getVertices()) { + Point2D xyd = transform(v); + vertices[index] = v; + xydata[index] = xyd; + index++; + } + break; + } catch(ConcurrentModificationException cme) {} + } + + diameter = DistanceStatistics.diameter(graph, distance, true); + + double L0 = Math.min(height, width); + L = (L0 / diameter) * length_factor; // length_factor used to be hardcoded to 0.9 + //L = 0.75 * Math.sqrt(height * width / n); + + for (int i = 0; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + Number d_ij = distance.getDistance(vertices[i], vertices[j]); + Number d_ji = distance.getDistance(vertices[j], vertices[i]); + double dist = diameter * disconnected_multiplier; + if (d_ij != null) + dist = Math.min(d_ij.doubleValue(), dist); + if (d_ji != null) + dist = Math.min(d_ji.doubleValue(), dist); + dm[i][j] = dm[j][i] = dist; + } + } + } + } + + public void step() { + try { + currentIteration++; + double energy = calcEnergy(); + status = "Kamada-Kawai V=" + getGraph().getVertexCount() + + "(" + getGraph().getVertexCount() + ")" + + " IT: " + currentIteration + + " E=" + energy + ; + + int n = getGraph().getVertexCount(); + if (n == 0) + return; + + double maxDeltaM = 0; + int pm = -1; // the node having max deltaM + for (int i = 0; i < n; i++) { + if (isLocked(vertices[i])) + continue; + double deltam = calcDeltaM(i); + + if (maxDeltaM < deltam) { + maxDeltaM = deltam; + pm = i; + } + } + if (pm == -1) + return; + + for (int i = 0; i < 100; i++) { + double[] dxy = calcDeltaXY(pm); + xydata[pm].setLocation(xydata[pm].getX()+dxy[0], xydata[pm].getY()+dxy[1]); + + double deltam = calcDeltaM(pm); + if (deltam < EPSILON) + break; + } + + if (adjustForGravity) + adjustForGravity(); + + if (exchangeVertices && maxDeltaM < EPSILON) { + energy = calcEnergy(); + for (int i = 0; i < n - 1; i++) { + if (isLocked(vertices[i])) + continue; + for (int j = i + 1; j < n; j++) { + if (isLocked(vertices[j])) + continue; + double xenergy = calcEnergyIfExchanged(i, j); + if (energy > xenergy) { + double sx = xydata[i].getX(); + double sy = xydata[i].getY(); + xydata[i].setLocation(xydata[j]); + xydata[j].setLocation(sx, sy); + return; + } + } + } + } + } + finally { +// fireStateChanged(); + } + } + + /** + * Shift all vertices so that the center of gravity is located at + * the center of the screen. + */ + public void adjustForGravity() { + Dimension d = getSize(); + double height = d.getHeight(); + double width = d.getWidth(); + double gx = 0; + double gy = 0; + for (int i = 0; i < xydata.length; i++) { + gx += xydata[i].getX(); + gy += xydata[i].getY(); + } + gx /= xydata.length; + gy /= xydata.length; + double diffx = width / 2 - gx; + double diffy = height / 2 - gy; + for (int i = 0; i < xydata.length; i++) { + xydata[i].setLocation(xydata[i].getX()+diffx, xydata[i].getY()+diffy); + } + } + + /* (non-Javadoc) + * @see edu.uci.ics.jung.visualization.layout.AbstractLayout#setSize(java.awt.Dimension) + */ + @Override + public void setSize(Dimension size) { + if(initialized == false) + setInitializer(new RandomLocationTransformer(size)); + super.setSize(size); + } + + /** + * Enable or disable gravity point adjusting. + */ + public void setAdjustForGravity(boolean on) { + adjustForGravity = on; + } + + /** + * Returns true if gravity point adjusting is enabled. + */ + public boolean getAdjustForGravity() { + return adjustForGravity; + } + + /** + * Enable or disable the local minimum escape technique by + * exchanging vertices. + */ + public void setExchangeVertices(boolean on) { + exchangeVertices = on; + } + + /** + * Returns true if the local minimum escape technique by + * exchanging vertices is enabled. + */ + public boolean getExchangeVertices() { + return exchangeVertices; + } + + /** + * Determines a step to new position of the vertex m. + */ + private double[] calcDeltaXY(int m) { + double dE_dxm = 0; + double dE_dym = 0; + double d2E_d2xm = 0; + double d2E_dxmdym = 0; + double d2E_dymdxm = 0; + double d2E_d2ym = 0; + + for (int i = 0; i < vertices.length; i++) { + if (i != m) { + + double dist = dm[m][i]; + double l_mi = L * dist; + double k_mi = K / (dist * dist); + double dx = xydata[m].getX() - xydata[i].getX(); + double dy = xydata[m].getY() - xydata[i].getY(); + double d = Math.sqrt(dx * dx + dy * dy); + double ddd = d * d * d; + + dE_dxm += k_mi * (1 - l_mi / d) * dx; + dE_dym += k_mi * (1 - l_mi / d) * dy; + d2E_d2xm += k_mi * (1 - l_mi * dy * dy / ddd); + d2E_dxmdym += k_mi * l_mi * dx * dy / ddd; + d2E_d2ym += k_mi * (1 - l_mi * dx * dx / ddd); + } + } + // d2E_dymdxm equals to d2E_dxmdym. + d2E_dymdxm = d2E_dxmdym; + + double denomi = d2E_d2xm * d2E_d2ym - d2E_dxmdym * d2E_dymdxm; + double deltaX = (d2E_dxmdym * dE_dym - d2E_d2ym * dE_dxm) / denomi; + double deltaY = (d2E_dymdxm * dE_dxm - d2E_d2xm * dE_dym) / denomi; + return new double[]{deltaX, deltaY}; + } + + /** + * Calculates the gradient of energy function at the vertex m. + */ + private double calcDeltaM(int m) { + double dEdxm = 0; + double dEdym = 0; + for (int i = 0; i < vertices.length; i++) { + if (i != m) { + double dist = dm[m][i]; + double l_mi = L * dist; + double k_mi = K / (dist * dist); + + double dx = xydata[m].getX() - xydata[i].getX(); + double dy = xydata[m].getY() - xydata[i].getY(); + double d = Math.sqrt(dx * dx + dy * dy); + + double common = k_mi * (1 - l_mi / d); + dEdxm += common * dx; + dEdym += common * dy; + } + } + return Math.sqrt(dEdxm * dEdxm + dEdym * dEdym); + } + + /** + * Calculates the energy function E. + */ + private double calcEnergy() { + double energy = 0; + for (int i = 0; i < vertices.length - 1; i++) { + for (int j = i + 1; j < vertices.length; j++) { + double dist = dm[i][j]; + double l_ij = L * dist; + double k_ij = K / (dist * dist); + double dx = xydata[i].getX() - xydata[j].getX(); + double dy = xydata[i].getY() - xydata[j].getY(); + double d = Math.sqrt(dx * dx + dy * dy); + + + energy += k_ij / 2 * (dx * dx + dy * dy + l_ij * l_ij - + 2 * l_ij * d); + } + } + return energy; + } + + /** + * Calculates the energy function E as if positions of the + * specified vertices are exchanged. + */ + private double calcEnergyIfExchanged(int p, int q) { + if (p >= q) + throw new RuntimeException("p should be < q"); + double energy = 0; // < 0 + for (int i = 0; i < vertices.length - 1; i++) { + for (int j = i + 1; j < vertices.length; j++) { + int ii = i; + int jj = j; + if (i == p) ii = q; + if (j == q) jj = p; + + double dist = dm[i][j]; + double l_ij = L * dist; + double k_ij = K / (dist * dist); + double dx = xydata[ii].getX() - xydata[jj].getX(); + double dy = xydata[ii].getY() - xydata[jj].getY(); + double d = Math.sqrt(dx * dx + dy * dy); + + energy += k_ij / 2 * (dx * dx + dy * dy + l_ij * l_ij - + 2 * l_ij * d); + } + } + return energy; + } + + public void reset() { + currentIteration = 0; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/Layout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/Layout.java new file mode 100644 index 0000000000..5162ac5972 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/Layout.java @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Graph; + +/** + * A generalized interface is a mechanism for returning (x,y) coordinates + * from vertices. In general, most of these methods are used to both control and + * get information from the layout algorithm. + *

      + * @author danyelf + * @author tom nelson + */ +public interface Layout extends Transformer { + + /** + * Initializes fields in the node that may not have + * been set during the constructor. Must be called before + * the iterations begin. + */ + void initialize(); + + /** + * provides initial locations for all vertices. + * @param initializer + */ + void setInitializer(Transformer initializer); + + /** + * setter for graph + * @param graph + */ + void setGraph(Graph graph); + + /** + * Returns the full graph (the one that was passed in at + * construction time) that this Layout refers to. + * + */ + Graph getGraph(); + + /** + * + * + */ + void reset(); + + /** + * @param d + */ + void setSize(Dimension d); + + /** + * Returns the current size of the visualization's space. + */ + Dimension getSize(); + + + /** + * Sets a flag which fixes this vertex in place. + * + * @param v vertex + */ + void lock(V v, boolean state); + + /** + * Returns true if the position of vertex v + * is locked. + */ + boolean isLocked(V v); + + /** + * set the location of a vertex + * @param v + * @param location + */ + void setLocation(V v, Point2D location); + + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/LayoutDecorator.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/LayoutDecorator.java new file mode 100644 index 0000000000..b1f25958cb --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/LayoutDecorator.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2005, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * Created on Aug 23, 2005 + */ + +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; + +/** + * a pure decorator for the Layout interface. Intended to be overridden + * to provide specific behavior decoration + * + * @author Tom Nelson + * + */ +public abstract class LayoutDecorator implements Layout, IterativeContext { + + protected Layout delegate; + + /** + * Creates an instance backed by the specified delegate layout. + */ + public LayoutDecorator(Layout delegate) { + this.delegate = delegate; + } + + /** + * Returns the backing (delegate) layout. + */ + public Layout getDelegate() { + return delegate; + } + + /** + * Sets the backing (delegate) layout. + */ + public void setDelegate(Layout delegate) { + this.delegate = delegate; + } + + /** + * @see edu.uci.ics.jung.algorithms.util.IterativeContext#done() + */ + public void step() { + if(delegate instanceof IterativeContext) { + ((IterativeContext)delegate).step(); + } + } + + /** + * + * @see edu.uci.ics.jung.algorithms.layout.Layout#initialize() + */ + public void initialize() { + delegate.initialize(); + } + + /** + * @param initializer + * @see edu.uci.ics.jung.algorithms.layout.Layout#setInitializer(org.apache.commons.collections15.Transformer) + */ + public void setInitializer(Transformer initializer) { + delegate.setInitializer(initializer); + } + + /** + * @param v + * @param location + * @see edu.uci.ics.jung.algorithms.layout.Layout#setLocation(java.lang.Object, java.awt.geom.Point2D) + */ + public void setLocation(V v, Point2D location) { + delegate.setLocation(v, location); + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.Layout#getSize() + */ + public Dimension getSize() { + return delegate.getSize(); + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.Layout#getGraph() + */ + public Graph getGraph() { + return delegate.getGraph(); + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.Layout#transform(Object) + */ + public Point2D transform(V v) { + return delegate.transform(v); + } + + /** + * @see edu.uci.ics.jung.algorithms.util.IterativeContext#done() + */ + public boolean done() { + if(delegate instanceof IterativeContext) { + return ((IterativeContext)delegate).done(); + } + return true; + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.Layout#lock(Object, boolean) + */ + public void lock(V v, boolean state) { + delegate.lock(v, state); + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.Layout#isLocked(Object) + */ + public boolean isLocked(V v) { + return delegate.isLocked(v); + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.Layout#setSize(Dimension) + */ + public void setSize(Dimension d) { + delegate.setSize(d); + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.Layout#reset() + */ + public void reset() { + delegate.reset(); + } + + public void setGraph(Graph graph) { + delegate.setGraph(graph); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/PolarPoint.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/PolarPoint.java new file mode 100644 index 0000000000..aa3dc7b411 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/PolarPoint.java @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.geom.Point2D; + +/** + * Represents a point in polar coordinates: distance and angle from the origin. + * Includes conversions between polar and Cartesian + * coordinates (Point2D). + * + * @author Tom Nelson - tomnelson@dev.java.net + */ +public class PolarPoint +{ + double theta; + double radius; + + /** + * Creates a new instance with radius and angle each 0. + */ + public PolarPoint() { + this(0,0); + } + + /** + * Creates a new instance with radius {@code radius} and angle {@code theta}. + */ + public PolarPoint(double theta, double radius) { + this.theta = theta; + this.radius = radius; + } + + /** + * Returns the angle for this point. + */ + public double getTheta() { return theta; } + + /** + * Returns the radius for this point. + */ + public double getRadius() { return radius; } + + /** + * Sets the angle for this point to {@code theta}. + */ + public void setTheta(double theta) { this.theta = theta; } + + /** + * Sets the radius for this point to {@code theta}. + */ + public void setRadius(double radius) { this.radius = radius; } + + /** + * Returns the result of converting polar to Cartesian coordinates. + */ + public static Point2D polarToCartesian(PolarPoint polar) { + return polarToCartesian(polar.getTheta(), polar.getRadius()); + } + + /** + * Returns the result of converting (theta, radius) to Cartesian coordinates. + */ + public static Point2D polarToCartesian(double theta, double radius) { + return new Point2D.Double(radius*Math.cos(theta), radius*Math.sin(theta)); + } + + /** + * Returns the result of converting point to polar coordinates. + */ + public static PolarPoint cartesianToPolar(Point2D point) { + return cartesianToPolar(point.getX(), point.getY()); + } + + /** + * Returns the result of converting (x, y) to polar coordinates. + */ + public static PolarPoint cartesianToPolar(double x, double y) { + double theta = Math.atan2(y,x); + double radius = Math.sqrt(x*x+y*y); + return new PolarPoint(theta, radius); + } + + @Override + public String toString() { + return "PolarPoint[" + radius + "," + theta +"]"; + } + + /** + * Sets the angle and radius of this point to those of {@code p}. + */ + public void setLocation(PolarPoint p) { + this.theta = p.getTheta(); + this.radius = p.getRadius(); + } +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/RadialTreeLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/RadialTreeLayout.java new file mode 100644 index 0000000000..457bd961f1 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/RadialTreeLayout.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2005, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * Created on Jul 9, 2005 + */ + +package edu.uci.ics.jung.algorithms.layout; +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.graph.Forest; + +/** + * A radial layout for Tree or Forest graphs. + * + * @author Tom Nelson + * + */ +public class RadialTreeLayout extends TreeLayout { + + protected Map polarLocations; + + /** + * Creates an instance for the specified graph with default X and Y distances. + */ + public RadialTreeLayout(Forest g) { + this(g, DEFAULT_DISTX, DEFAULT_DISTY); + } + + /** + * Creates an instance for the specified graph and X distance with + * default Y distance. + */ + public RadialTreeLayout(Forest g, int distx) { + this(g, distx, DEFAULT_DISTY); + } + + /** + * Creates an instance for the specified graph, X distance, and Y distance. + */ + public RadialTreeLayout(Forest g, int distx, int disty) { + super(g, distx, disty); + } + + @Override + protected void buildTree() { + super.buildTree(); + this.polarLocations = new HashMap(); + setRadialLocations(); + } + + @Override + public void setSize(Dimension size) { + this.size = size; + buildTree(); + } + + @Override + protected void setCurrentPositionFor(V vertex) { + locations.get(vertex).setLocation(m_currentPoint); + } + + @Override + public void setLocation(V v, Point2D location) + { + Point2D c = getCenter(); + Point2D pv = new Point2D.Double(location.getX() - c.getX(), + location.getY() - c.getY()); + PolarPoint newLocation = PolarPoint.cartesianToPolar(pv); + PolarPoint currentLocation = polarLocations.get(v); + if (currentLocation == null) + polarLocations.put(v, newLocation); + else + currentLocation.setLocation(newLocation); + } + + /** + * Returns the map from vertices to their locations in polar coordinates. + */ + public Map getPolarLocations() { + return polarLocations; + } + + @Override + public Point2D transform(V v) { + PolarPoint pp = polarLocations.get(v); + double centerX = getSize().getWidth()/2; + double centerY = getSize().getHeight()/2; + Point2D cartesian = PolarPoint.polarToCartesian(pp); + cartesian.setLocation(cartesian.getX()+centerX,cartesian.getY()+centerY); + return cartesian; + } + + private Point2D getMaxXY() { + double maxx = 0; + double maxy = 0; + for(Point2D p : locations.values()) { + maxx = Math.max(maxx, p.getX()); + maxy = Math.max(maxy, p.getY()); + } + return new Point2D.Double(maxx,maxy); + } + + private void setRadialLocations() { + Point2D max = getMaxXY(); + double maxx = max.getX(); + double maxy = max.getY(); + maxx = Math.max(maxx, size.width); + double theta = 2*Math.PI/maxx; + + double deltaRadius = size.width/2/maxy; + for(Map.Entry entry : locations.entrySet()) { + V v = entry.getKey(); + Point2D p = entry.getValue(); + PolarPoint polarPoint = new PolarPoint(p.getX()*theta, (p.getY() - this.distY)*deltaRadius); + polarLocations.put(v, polarPoint); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/RadiusGraphElementAccessor.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/RadiusGraphElementAccessor.java new file mode 100644 index 0000000000..5f12c3ca4e --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/RadiusGraphElementAccessor.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2005, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * + * Created on Apr 12, 2005 + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Shape; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import edu.uci.ics.jung.graph.Graph; + + +/** + * Simple implementation of PickSupport that returns the vertex or edge + * that is closest to the specified location. This implementation + * provides the same picking options that were available in + * previous versions of AbstractLayout. + * + *

      No element will be returned that is farther away than the specified + * maximum distance. + * + * @author Tom Nelson + * @author Joshua O'Madadhain + */ +public class RadiusGraphElementAccessor implements GraphElementAccessor { + + protected double maxDistance; + + /** + * Creates an instance with an effectively infinite default maximum distance. + */ + public RadiusGraphElementAccessor() { + this(Math.sqrt(Double.MAX_VALUE - 1000)); + } + + /** + * Creates an instance with the specified default maximum distance. + */ + public RadiusGraphElementAccessor(double maxDistance) { + this.maxDistance = maxDistance; + } + + /** + * Gets the vertex nearest to the location of the (x,y) location selected, + * within a distance of maxDistance. Iterates through all + * visible vertices and checks their distance from the click. Override this + * method to provde a more efficient implementation. + */ + public V getVertex(Layout layout, double x, double y) { + return getVertex(layout, x, y, this.maxDistance); + } + + /** + * Gets the vertex nearest to the location of the (x,y) location selected, + * within a distance of maxDistance. Iterates through all + * visible vertices and checks their distance from the click. Override this + * method to provde a more efficient implementation. + * @param x + * @param y + * @param maxDistance temporarily overrides member maxDistance + */ + public V getVertex(Layout layout, double x, double y, double maxDistance) { + double minDistance = maxDistance * maxDistance; + V closest = null; + while(true) { + try { + for(V v : layout.getGraph().getVertices()) { + + Point2D p = layout.transform(v); + double dx = p.getX() - x; + double dy = p.getY() - y; + double dist = dx * dx + dy * dy; + if (dist < minDistance) { + minDistance = dist; + closest = v; + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } + + public Collection getVertices(Layout layout, Shape rectangle) { + Set pickedVertices = new HashSet(); + while(true) { + try { + for(V v : layout.getGraph().getVertices()) { + + Point2D p = layout.transform(v); + if(rectangle.contains(p)) { + pickedVertices.add(v); + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return pickedVertices; + } + + /** + * Gets the edge nearest to the location of the (x,y) location selected. + * Calls the longer form of the call. + */ + public E getEdge(Layout layout, double x, double y) { + return getEdge(layout, x, y, this.maxDistance); + } + + /** + * Gets the edge nearest to the location of the (x,y) location selected, + * within a distance of maxDistance, Iterates through all + * visible edges and checks their distance from the click. Override this + * method to provide a more efficient implementation. + * + * @param x + * @param y + * @param maxDistance temporarily overrides member maxDistance + * @return Edge closest to the click. + */ + public E getEdge(Layout layout, double x, double y, double maxDistance) { + double minDistance = maxDistance * maxDistance; + E closest = null; + while(true) { + try { + for(E e : layout.getGraph().getEdges()) { + + // Could replace all this set stuff with getFrom_internal() etc. + Graph graph = layout.getGraph(); + Collection vertices = graph.getIncidentVertices(e); + Iterator vertexIterator = vertices.iterator(); + V v1 = vertexIterator.next(); + V v2 = vertexIterator.next(); + // Get coords + Point2D p1 = layout.transform(v1); + Point2D p2 = layout.transform(v2); + double x1 = p1.getX(); + double y1 = p1.getY(); + double x2 = p2.getX(); + double y2 = p2.getY(); + // Calculate location on line closest to (x,y) + // First, check that v1 and v2 are not coincident. + if (x1 == x2 && y1 == y2) + continue; + double b = + ((y - y1) * (y2 - y1) + (x - x1) * (x2 - x1)) + / ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + // + double distance2; // square of the distance + if (b <= 0) + distance2 = (x - x1) * (x - x1) + (y - y1) * (y - y1); + else if (b >= 1) + distance2 = (x - x2) * (x - x2) + (y - y2) * (y - y2); + else { + double x3 = x1 + b * (x2 - x1); + double y3 = y1 + b * (y2 - y1); + distance2 = (x - x3) * (x - x3) + (y - y3) * (y - y3); + } + + if (distance2 < minDistance) { + minDistance = distance2; + closest = e; + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout.java new file mode 100644 index 0000000000..d21c2a158e --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout.java @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.functors.ConstantTransformer; +import org.apache.commons.collections15.map.LazyMap; + +import java.awt.Dimension; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Map; + +/** + * The SpringLayout package represents a visualization of a set of nodes. The + * SpringLayout, which is initialized with a Graph, assigns X/Y locations to + * each node. When called relax(), the SpringLayout moves the + * visualization forward one step. + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +public class SpringLayout extends AbstractLayout implements IterativeContext { + + protected double stretch = 0.70; + protected Transformer lengthFunction; + protected int repulsion_range_sq = 100 * 100; + protected double force_multiplier = 1.0 / 3.0; + + protected Map springVertexData = + LazyMap.decorate(new HashMap(), + new Factory() { + public SpringVertexData create() { + return new SpringVertexData(); + }}); + + /** + * Constructor for a SpringLayout for a raw graph with associated + * dimension--the input knows how big the graph is. Defaults to the unit + * length function. + */ + @SuppressWarnings("unchecked") + public SpringLayout(Graph g) { + this(g, new ConstantTransformer(30)); + } + + /** + * Constructor for a SpringLayout for a raw graph with associated component. + * + * @param g the {@code Graph} to lay out + * @param length_function provides a length for each edge + */ + public SpringLayout(Graph g, Transformer length_function) + { + super(g); + this.lengthFunction = length_function; + } + + /** + * Returns the current value for the stretch parameter. + * @see #setStretch(double) + */ + public double getStretch() { + return stretch; + } + + /** + * Sets the dimensions of the available space for layout to {@code size}. + */ + @Override + public void setSize(Dimension size) { + if(initialized == false) + setInitializer(new RandomLocationTransformer(size)); + super.setSize(size); + } + + /** + *

      Sets the stretch parameter for this instance. This value + * specifies how much the degrees of an edge's incident vertices + * should influence how easily the endpoints of that edge + * can move (that is, that edge's tendency to change its length).

      + * + *

      The default value is 0.70. Positive values less than 1 cause + * high-degree vertices to move less than low-degree vertices, and + * values > 1 cause high-degree vertices to move more than + * low-degree vertices. Negative values will have unpredictable + * and inconsistent results.

      + * @param stretch + */ + public void setStretch(double stretch) { + this.stretch = stretch; + } + + /** + * Returns the current value for the node repulsion range. + * @see #setRepulsionRange(int) + */ + public int getRepulsionRange() { + return (int)(Math.sqrt(repulsion_range_sq)); + } + + /** + * Sets the node repulsion range (in drawing area units) for this instance. + * Outside this range, nodes do not repel each other. The default value + * is 100. Negative values are treated as their positive equivalents. + * @param range + */ + public void setRepulsionRange(int range) { + this.repulsion_range_sq = range * range; + } + + /** + * Returns the current value for the edge length force multiplier. + * @see #setForceMultiplier(double) + */ + public double getForceMultiplier() { + return force_multiplier; + } + + /** + * Sets the force multiplier for this instance. This value is used to + * specify how strongly an edge "wants" to be its default length + * (higher values indicate a greater attraction for the default length), + * which affects how much its endpoints move at each timestep. + * The default value is 1/3. A value of 0 turns off any attempt by the + * layout to cause edges to conform to the default length. Negative + * values cause long edges to get longer and short edges to get shorter; use + * at your own risk. + */ + public void setForceMultiplier(double force) { + this.force_multiplier = force; + } + + public void initialize() { + } + + /** + * Relaxation step. Moves all nodes a smidge. + */ + public void step() { + try { + for(V v : getGraph().getVertices()) { + SpringVertexData svd = springVertexData.get(v); + if (svd == null) { + continue; + } + svd.dx /= 4; + svd.dy /= 4; + svd.edgedx = svd.edgedy = 0; + svd.repulsiondx = svd.repulsiondy = 0; + } + } catch(ConcurrentModificationException cme) { + step(); + } + + relaxEdges(); + calculateRepulsion(); + moveNodes(); + } + + protected void relaxEdges() { + try { + for(E e : getGraph().getEdges()) { + Pair endpoints = getGraph().getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + Point2D p1 = transform(v1); + Point2D p2 = transform(v2); + if(p1 == null || p2 == null) continue; + double vx = p1.getX() - p2.getX(); + double vy = p1.getY() - p2.getY(); + double len = Math.sqrt(vx * vx + vy * vy); + + double desiredLen = lengthFunction.transform(e); + + // round from zero, if needed [zero would be Bad.]. + len = (len == 0) ? .0001 : len; + + double f = force_multiplier * (desiredLen - len) / len; + + f = f * Math.pow(stretch, (getGraph().degree(v1) + getGraph().degree(v2) - 2)); + + // the actual movement distance 'dx' is the force multiplied by the + // distance to go. + double dx = f * vx; + double dy = f * vy; + SpringVertexData v1D, v2D; + v1D = springVertexData.get(v1); + v2D = springVertexData.get(v2); + + v1D.edgedx += dx; + v1D.edgedy += dy; + v2D.edgedx += -dx; + v2D.edgedy += -dy; + } + } catch(ConcurrentModificationException cme) { + relaxEdges(); + } + } + + protected void calculateRepulsion() { + try { + for (V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + + SpringVertexData svd = springVertexData.get(v); + if(svd == null) continue; + double dx = 0, dy = 0; + + for (V v2 : getGraph().getVertices()) { + if (v == v2) continue; + Point2D p = transform(v); + Point2D p2 = transform(v2); + if(p == null || p2 == null) continue; + double vx = p.getX() - p2.getX(); + double vy = p.getY() - p2.getY(); + double distanceSq = p.distanceSq(p2); + if (distanceSq == 0) { + dx += Math.random(); + dy += Math.random(); + } else if (distanceSq < repulsion_range_sq) { + double factor = 1; + dx += factor * vx / distanceSq; + dy += factor * vy / distanceSq; + } + } + double dlen = dx * dx + dy * dy; + if (dlen > 0) { + dlen = Math.sqrt(dlen) / 2; + svd.repulsiondx += dx / dlen; + svd.repulsiondy += dy / dlen; + } + } + } catch(ConcurrentModificationException cme) { + calculateRepulsion(); + } + } + + protected void moveNodes() + { + synchronized (getSize()) { + try { + for (V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + SpringVertexData vd = springVertexData.get(v); + if(vd == null) continue; + Point2D xyd = transform(v); + + vd.dx += vd.repulsiondx + vd.edgedx; + vd.dy += vd.repulsiondy + vd.edgedy; + + // keeps nodes from moving any faster than 5 per time unit + xyd.setLocation(xyd.getX()+Math.max(-5, Math.min(5, vd.dx)), + xyd.getY()+Math.max(-5, Math.min(5, vd.dy))); + + Dimension d = getSize(); + int width = d.width; + int height = d.height; + + if (xyd.getX() < 0) { + xyd.setLocation(0, xyd.getY()); + } else if (xyd.getX() > width) { + xyd.setLocation(width, xyd.getY()); + } + if (xyd.getY() < 0) { + xyd.setLocation(xyd.getX(), 0); + } else if (xyd.getY() > height) { + xyd.setLocation(xyd.getX(), height); + } + + } + } catch(ConcurrentModificationException cme) { + moveNodes(); + } + } + } + + protected static class SpringVertexData { + protected double edgedx; + protected double edgedy; + protected double repulsiondx; + protected double repulsiondy; + + /** movement speed, x */ + protected double dx; + + /** movement speed, y */ + protected double dy; + } + + + /** + * Used for changing the size of the layout in response to a component's size. + */ + public class SpringDimensionChecker extends ComponentAdapter { + @Override + public void componentResized(ComponentEvent e) { + setSize(e.getComponent().getSize()); + } + } + + /** + * This one is an incremental visualization + */ + public boolean isIncremental() { + return true; + } + + /** + * For now, we pretend it never finishes. + */ + public boolean done() { + return false; + } + + /** + * No effect. + */ + public void reset() { + } +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout2.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout2.java new file mode 100644 index 0000000000..e62a30c198 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout2.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Graph; + +/** + * The SpringLayout package represents a visualization of a set of nodes. The + * SpringLayout, which is initialized with a Graph, assigns X/Y locations to + * each node. When called relax(), the SpringLayout moves the + * visualization forward one step. + * + * + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +public class SpringLayout2 extends SpringLayout +{ + protected int currentIteration; + protected int averageCounter; + protected int loopCountMax = 4; + protected boolean done; + + protected Point2D averageDelta = new Point2D.Double(); + + /** + * Constructor for a SpringLayout for a raw graph with associated + * dimension--the input knows how big the graph is. Defaults to the unit + * length function. + */ + @SuppressWarnings("unchecked") + public SpringLayout2(Graph g) { + super(g); + } + + /** + * Constructor for a SpringLayout for a raw graph with associated component. + * + * @param g the {@code Graph} to lay out + * @param length_function provides a length for each edge + */ + public SpringLayout2(Graph g, Transformer length_function) + { + super(g, length_function); + } + + /** + * Relaxation step. Moves all nodes a smidge. + */ + @Override + public void step() { + super.step(); + currentIteration++; + testAverageDeltas(); + } + + private void testAverageDeltas() { + double dx = this.averageDelta.getX(); + double dy = this.averageDelta.getY(); + if(Math.abs(dx) < .001 && Math.abs(dy) < .001) { + done = true; + System.err.println("done, dx="+dx+", dy="+dy); + } + if(currentIteration > loopCountMax) { + this.averageDelta.setLocation(0,0); + averageCounter = 0; + currentIteration = 0; + } + } + + @Override + protected void moveNodes() { + synchronized (getSize()) { + try { + for (V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + SpringVertexData vd = springVertexData.get(v); + if(vd == null) continue; + Point2D xyd = transform(v); + + vd.dx += vd.repulsiondx + vd.edgedx; + vd.dy += vd.repulsiondy + vd.edgedy; + +// int currentCount = currentIteration % this.loopCountMax; +// System.err.println(averageCounter+" --- vd.dx="+vd.dx+", vd.dy="+vd.dy); +// System.err.println("averageDelta was "+averageDelta); + + averageDelta.setLocation( + ((averageDelta.getX() * averageCounter) + vd.dx) / (averageCounter+1), + ((averageDelta.getY() * averageCounter) + vd.dy) / (averageCounter+1) + ); +// System.err.println("averageDelta now "+averageDelta); +// System.err.println(); + averageCounter++; + + // keeps nodes from moving any faster than 5 per time unit + xyd.setLocation(xyd.getX()+Math.max(-5, Math.min(5, vd.dx)), + xyd.getY()+Math.max(-5, Math.min(5, vd.dy))); + + Dimension d = getSize(); + int width = d.width; + int height = d.height; + + if (xyd.getX() < 0) { + xyd.setLocation(0, xyd.getY());// setX(0); + } else if (xyd.getX() > width) { + xyd.setLocation(width, xyd.getY()); //setX(width); + } + if (xyd.getY() < 0) { + xyd.setLocation(xyd.getX(),0);//setY(0); + } else if (xyd.getY() > height) { + xyd.setLocation(xyd.getX(), height); //setY(height); + } + + } + } catch(ConcurrentModificationException cme) { + moveNodes(); + } + } + } + + @Override + public boolean done() { + return done; + } + +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/StaticLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/StaticLayout.java new file mode 100644 index 0000000000..31b32554c2 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/StaticLayout.java @@ -0,0 +1,69 @@ +/* + * Created on Jul 21, 2005 + * + * Copyright (c) 2005, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Graph; + +/** + * StaticLayout places the vertices in the locations specified by its Transformer + * initializer. Vertex locations can be placed in a Map and then supplied to + * this layout as follows: + * + Transformer vertexLocations = + TransformerUtils.mapTransformer(map); + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param + * @param + */ +public class StaticLayout extends AbstractLayout { + + /** + * Creates an instance for the specified graph, locations, and size. + */ + public StaticLayout(Graph graph, Transformer initializer, Dimension size) { + super(graph, initializer, size); + } + + /** + * Creates an instance for the specified graph and locations, with default size. + */ + public StaticLayout(Graph graph, Transformer initializer) { + super(graph, initializer); + } + + /** + * Creates an instance for the specified graph and default size; vertex locations + * are randomly assigned. + */ + public StaticLayout(Graph graph) { + super(graph); + } + + /** + * Creates an instance for the specified graph and size. + */ + public StaticLayout(Graph graph, Dimension size) { + super(graph, size); + } + + public void initialize() {} + + public void reset() {} + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/TreeLayout.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/TreeLayout.java new file mode 100644 index 0000000000..4bebd3a9b1 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/TreeLayout.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2005, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * Created on Jul 9, 2005 + */ + +package edu.uci.ics.jung.algorithms.layout; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.map.LazyMap; + +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TreeUtils; + +/** + * @author Karlheinz Toni + * @author Tom Nelson - converted to jung2 + * + */ + +public class TreeLayout implements Layout { + + protected Dimension size = new Dimension(600,600); + protected Forest graph; + protected Map basePositions = new HashMap(); + + protected Map locations = + LazyMap.decorate(new HashMap(), + new Transformer() { + public Point2D transform(V arg0) { + return new Point2D.Double(); + }}); + + protected transient Set alreadyDone = new HashSet(); + + /** + * The default horizontal vertex spacing. Initialized to 50. + */ + public static int DEFAULT_DISTX = 50; + + /** + * The default vertical vertex spacing. Initialized to 50. + */ + public static int DEFAULT_DISTY = 50; + + /** + * The horizontal vertex spacing. Defaults to {@code DEFAULT_XDIST}. + */ + protected int distX = 50; + + /** + * The vertical vertex spacing. Defaults to {@code DEFAULT_YDIST}. + */ + protected int distY = 50; + + protected transient Point m_currentPoint = new Point(); + + /** + * Creates an instance for the specified graph with default X and Y distances. + */ + public TreeLayout(Forest g) { + this(g, DEFAULT_DISTX, DEFAULT_DISTY); + } + + /** + * Creates an instance for the specified graph and X distance with + * default Y distance. + */ + public TreeLayout(Forest g, int distx) { + this(g, distx, DEFAULT_DISTY); + } + + /** + * Creates an instance for the specified graph, X distance, and Y distance. + */ + public TreeLayout(Forest g, int distx, int disty) { + if (g == null) + throw new IllegalArgumentException("Graph must be non-null"); + if (distx < 1 || disty < 1) + throw new IllegalArgumentException("X and Y distances must each be positive"); + this.graph = g; + this.distX = distx; + this.distY = disty; + buildTree(); + } + + protected void buildTree() { + this.m_currentPoint = new Point(0, 20); + Collection roots = TreeUtils.getRoots(graph); + if (roots.size() > 0 && graph != null) { + calculateDimensionX(roots); + for(V v : roots) { + calculateDimensionX(v); + m_currentPoint.x += this.basePositions.get(v)/2 + this.distX; + buildTree(v, this.m_currentPoint.x); + } + } + int width = 0; + for(V v : roots) { + width += basePositions.get(v); + } + } + + protected void buildTree(V v, int x) { + + if (!alreadyDone.contains(v)) { + alreadyDone.add(v); + + //go one level further down + this.m_currentPoint.y += this.distY; + this.m_currentPoint.x = x; + + this.setCurrentPositionFor(v); + + int sizeXofCurrent = basePositions.get(v); + + int lastX = x - sizeXofCurrent / 2; + + int sizeXofChild; + int startXofChild; + + for (V element : graph.getSuccessors(v)) { + sizeXofChild = this.basePositions.get(element); + startXofChild = lastX + sizeXofChild / 2; + buildTree(element, startXofChild); + lastX = lastX + sizeXofChild + distX; + } + this.m_currentPoint.y -= this.distY; + } + } + + private int calculateDimensionX(V v) { + + int size = 0; + int childrenNum = graph.getSuccessors(v).size(); + + if (childrenNum != 0) { + for (V element : graph.getSuccessors(v)) { + size += calculateDimensionX(element) + distX; + } + } + size = Math.max(0, size - distX); + basePositions.put(v, size); + + return size; + } + + private int calculateDimensionX(Collection roots) { + + int size = 0; + for(V v : roots) { + int childrenNum = graph.getSuccessors(v).size(); + + if (childrenNum != 0) { + for (V element : graph.getSuccessors(v)) { + size += calculateDimensionX(element) + distX; + } + } + size = Math.max(0, size - distX); + basePositions.put(v, size); + } + + return size; + } + + /** + * This method is not supported by this class. The size of the layout + * is determined by the topology of the tree, and by the horizontal + * and vertical spacing (optionally set by the constructor). + */ + public void setSize(Dimension size) { + throw new UnsupportedOperationException("Size of TreeLayout is set" + + " by vertex spacing in constructor"); + } + + protected void setCurrentPositionFor(V vertex) { + int x = m_currentPoint.x; + int y = m_currentPoint.y; + if(x < 0) size.width -= x; + + if(x > size.width-distX) + size.width = x + distX; + + if(y < 0) size.height -= y; + if(y > size.height-distY) + size.height = y + distY; + locations.get(vertex).setLocation(m_currentPoint); + + } + + public Graph getGraph() { + return graph; + } + + public Dimension getSize() { + return size; + } + + public void initialize() { + + } + + public boolean isLocked(V v) { + return false; + } + + public void lock(V v, boolean state) { + } + + public void reset() { + } + + public void setGraph(Graph graph) { + if(graph instanceof Forest) { + this.graph = (Forest)graph; + buildTree(); + } else { + throw new IllegalArgumentException("graph must be a Forest"); + } + } + + public void setInitializer(Transformer initializer) { + } + + /** + * Returns the center of this layout's area. + */ + public Point2D getCenter() { + return new Point2D.Double(size.getWidth()/2,size.getHeight()/2); + } + + public void setLocation(V v, Point2D location) { + locations.get(v).setLocation(location); + } + + public Point2D transform(V v) { + return locations.get(v); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/package.html new file mode 100644 index 0000000000..a5ed0d05a2 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/package.html @@ -0,0 +1,40 @@ + + + + + + + +Algorithms for assigning 2D coordinates (typically used for graph visualizations) +to vertices. +Current layout algorithms include: +
        +
      • Layout, AbstractLayout: interface and abstract class defining the Layout contract and handling +some common implementation details +
      • AggregateLayout: allows multiple layouts to be combined and manipulated as one layout +
      • BalloonLayout: places vertices on nested circles (trees/forests only) +
      • CircleLayout: places vertices on a circle +
      • DAGLayout: places vertices in a hierarchy (directed acyclic graphs only) +
      • FRLayout: Fruchterman-Reingold algorithm (force-directed) +
      • ISOMLayout: self-organizing map layout +
      • KKLayout: Kamada-Kawai algorithm (tries to maintain specified distances) +
      • RadialTreeLayout: places vertices on concentric circles (trees only) +
      • SpringLayout: simple force-directed layout +
      • StaticLayout: places vertices at user-specified locations +
      • TreeLayout: simple tree/forest layout +
      + +Rendering and other aspects of visualization are handled in the visualization package. + + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/RandomLocationTransformer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/RandomLocationTransformer.java new file mode 100644 index 0000000000..34428b18fb --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/RandomLocationTransformer.java @@ -0,0 +1,59 @@ +/* + * Created on Jul 19, 2005 + * + * Copyright (c) 2005, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.layout.util; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.Date; +import java.util.Random; + +import org.apache.commons.collections15.Transformer; + +/** + * Transforms the input type into a random location within + * the bounds of the Dimension property. + * This is used as the backing Transformer for the LazyMap + * for many Layouts, + * and provides a random location for unmapped vertices + * the first time they are accessed. + * + * @author Tom Nelson + * + * @param + */ +public class RandomLocationTransformer implements Transformer { + + Dimension d; + Random random; + + /** + * Creates an instance with the specified size which uses the current time + * as the random seed. + */ + public RandomLocationTransformer(Dimension d) { + this(d, new Date().getTime()); + } + + /** + * Creates an instance with the specified dimension and random seed. + * @param d + * @param seed + */ + public RandomLocationTransformer(final Dimension d, long seed) { + this.d = d; + this.random = new Random(seed); + } + + public Point2D transform(V v) { + return new Point2D.Double(random.nextDouble() * d.width, random.nextDouble() * d.height); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/Relaxer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/Relaxer.java new file mode 100644 index 0000000000..a31113f190 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/Relaxer.java @@ -0,0 +1,43 @@ +package edu.uci.ics.jung.algorithms.layout.util; + +/** + * Interface for operating the relax iterations on a layout. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public interface Relaxer { + + /** + * Execute a loop of steps in a new Thread, + * firing an event after each step. + */ + void relax(); + + /** + * Execute a loop of steps in the calling + * thread, firing no events. + */ + void prerelax(); + + /** + * Make the relaxer thread wait. + */ + void pause(); + + /** + * Make the relaxer thread resume. + * + */ + void resume(); + + /** + * Set flags to stop the relaxer thread. + */ + void stop(); + + /** + * Sets the sleep time. + */ + void setSleepTime(long i); +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/VisRunner.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/VisRunner.java new file mode 100644 index 0000000000..14f6dfc86c --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/VisRunner.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2005, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + * + * + */ +package edu.uci.ics.jung.algorithms.layout.util; + +import edu.uci.ics.jung.algorithms.util.IterativeContext; + +/** + * + * Implementation of a relaxer thread for layouts. + * Extracted from the {@code VisualizationModel} in previous + * versions of JUNG. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class VisRunner implements Relaxer, Runnable { + + protected boolean running; + protected IterativeContext process; + protected boolean stop; + protected boolean manualSuspend; + protected Thread thread; + + /** + * how long the relaxer thread pauses between iteration loops. + */ + protected long sleepTime = 100L; + + + /** + * Creates an instance for the specified process. + */ + public VisRunner(IterativeContext process) { + this.process = process; + } + + /** + * @return the relaxerThreadSleepTime + */ + public long getSleepTime() { + return sleepTime; + } + + /** + * @param sleepTime the sleep time to set for this thread + */ + public void setSleepTime(long sleepTime) { + this.sleepTime = sleepTime; + } + + public void prerelax() { + manualSuspend = true; + long timeNow = System.currentTimeMillis(); + while (System.currentTimeMillis() - timeNow < 500 && !process.done()) { + process.step(); + } + manualSuspend = false; + } + + public void pause() { + manualSuspend = true; + } + + public void relax() { + // in case its running + stop(); + stop = false; + thread = new Thread(this); + thread.setPriority(Thread.MIN_PRIORITY); + thread.start(); + } + + /** + * Used for synchronization. + */ + public Object pauseObject = new String("PAUSE OBJECT"); + + public void resume() { + manualSuspend = false; + if(running == false) { + prerelax(); + relax(); + } else { + synchronized(pauseObject) { + pauseObject.notifyAll(); + } + } + } + + public synchronized void stop() { + if(thread != null) { + manualSuspend = false; + stop = true; + // interrupt the relaxer, in case it is paused or sleeping + // this should ensure that visRunnerIsRunning gets set to false + try { thread.interrupt(); } + catch(Exception ex) { + // the applet security manager may have prevented this. + // just sleep for a second to let the thread stop on its own + try { Thread.sleep(1000); } + catch(InterruptedException ie) {} // ignore + } + synchronized (pauseObject) { + pauseObject.notifyAll(); + } + } + } + + public void run() { + running = true; + try { + while (!process.done() && !stop) { + synchronized (pauseObject) { + while (manualSuspend && !stop) { + try { + pauseObject.wait(); + } catch (InterruptedException e) { + // ignore + } + } + } + process.step(); + + if (stop) + return; + + try { + Thread.sleep(sleepTime); + } catch (InterruptedException ie) { + // ignore + } + } + + } finally { + running = false; + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/package.html new file mode 100644 index 0000000000..356f7d5f32 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/layout/util/package.html @@ -0,0 +1,21 @@ + + + + + + + +Utility classes for updating layout positions. + + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/MatrixElementOperations.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/MatrixElementOperations.java new file mode 100644 index 0000000000..1124bdf0b0 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/MatrixElementOperations.java @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.matrix; + +import java.util.Map; + + +/** + * An interface for specifying the behavior of graph/matrix operations + * for a particular element type. + *

      + * Graph/matrix multiplication requires the definition of two operations: + *

      + *

        + *
      1. + * Calculating an aggregate property of paths of length 2 between two + * vertices v1 and v2 (analogous to element multiplication in matrix + * arithmetic); this is handled by computePathData(). + *
      2. + *
      3. + * Aggregating the properties of all such paths, and assigning the result to + * a new edge in the output graph (analogous to element addition in matrix + * arithmetic); this is handled by mergePaths(). + *
      4. + *
      + *

      + * Together, computePathData() and mergePaths() specify how the equivalent of + * the vector inner (dot) product is to function. + *

      + * For instance, to implement the equivalent of standard matrix multiplication + * on two graphs, computePathData() should return the products of the + * weights of a two-edge path, and mergePaths() should add + * the output of computePathData() to an existing edge (or possibly create such + * an edge if none exists). + * + * @author Joshua O'Madadhain + */ +public interface MatrixElementOperations +{ + /** + * If either e or pathData is null, the effect of mergePaths() is + * implementation-dependent. + * + * @param e (possibly) existing edge in the output graph which + * represents a path in the input graph(s) + * + * @param pathData data (which represents another path with the same source + * and destination as e in the input graphs) which is to be merged into e + */ + public void mergePaths(E e, Object pathData); + + /** + * If either e1 or e2 is null, the Object reference returned should be null. + * + * @param e1 first edge from 2-edge path in input graph(s) + * @param e2 second edge from 2-edge path in input graph(s) + * @return aggregation of data from the edges of the 2-edge path + * (from source of e1 to destination of e2) comprised of (e1, e2) + */ + public Number computePathData(E e1, E e2); + + /** + * Returns a map from edges to values. + */ + public Map getEdgeData(); +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/RealMatrixElementOperations.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/RealMatrixElementOperations.java new file mode 100644 index 0000000000..ada1406c48 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/RealMatrixElementOperations.java @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.matrix; + + +import java.util.HashMap; +import java.util.Map; + +/** + * Implements the basic matrix operations on double-precision values. Assumes + * that the edges have a MutableDouble value. + * + * @author Joshua O'Madadhain + */ +public class RealMatrixElementOperations implements MatrixElementOperations +{ + private Map edgeData = new HashMap(); + + /** + * Creates an instance using the specified edge values. + */ + public RealMatrixElementOperations(Map edgeData) + { + this.edgeData = edgeData; + } + + /** + * @see MatrixElementOperations#mergePaths(Object, Object) + */ + public void mergePaths(E e, Object pathData) + { + + Number pd = (Number)pathData; + Number ed = edgeData.get(e); + if (ed == null) { + edgeData.put(e, pd); + + } else { + edgeData.put(e, ed.doubleValue()+pd.doubleValue()); + + } + + } + + /** + * @see MatrixElementOperations#computePathData(Object, Object) + */ + public Number computePathData(E e1, E e2) + { + double d1 = edgeData.get(e1).doubleValue(); + double d2 = edgeData.get(e2).doubleValue(); + return d1*d2; + } + + /** + * @return the edgeData + */ + public Map getEdgeData() { + return edgeData; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/package.html new file mode 100644 index 0000000000..6025a412dc --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/matrix/package.html @@ -0,0 +1,20 @@ + + + + + + + +Mechanisms for dealing with graphs as matrices. These include conversion to and +from Colt matrices, and some matrix algorithms. + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/Metrics.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/Metrics.java new file mode 100644 index 0000000000..1dfcf12309 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/Metrics.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * Created on Jun 7, 2008 + * + */ +package edu.uci.ics.jung.algorithms.metrics; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.graph.Graph; + +/** + * A class consisting of static methods for calculating graph metrics. + */ +public class Metrics +{ + /** + * Returns a Map of vertices to their clustering coefficients. + * The clustering coefficient cc(v) of a vertex v is defined as follows: + *

        + *
      • degree(v) == {0,1}: 0 + *
      • degree(v) == n, n >= 2: given S, the set of neighbors + * of v: cc(v) = (the sum over all w in S of the number of + * other elements of w that are neighbors of w) / ((|S| * (|S| - 1) / 2). + * Less formally, the fraction of v's neighbors that are also + * neighbors of each other. + *

        Note: This algorithm treats its argument as an undirected graph; + * edge direction is ignored. + * @param graph the graph whose clustering coefficients are to be calculated + * @see "The structure and function of complex networks, M.E.J. Newman, aps.arxiv.org/abs/cond-mat/0303516" + */ + public static Map clusteringCoefficients(Graph graph) + { + Map coefficients = new HashMap(); + + for (V v : graph.getVertices()) + { + int n = graph.getNeighborCount(v); + if (n < 2) + coefficients.put(v, new Double(0)); + else + { + // how many of v's neighbors are connected to each other? + ArrayList neighbors = new ArrayList(graph.getNeighbors(v)); + double edge_count = 0; + for (int i = 0; i < n; i++) + { + V w = neighbors.get(i); + for (int j = i+1; j < n; j++ ) + { + V x = neighbors.get(j); + edge_count += graph.isNeighbor(w, x) ? 1 : 0; + } + } + double possible_edges = (n * (n - 1))/2.0; + coefficients.put(v, new Double(edge_count / possible_edges)); + } + } + + return coefficients; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/StructuralHoles.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/StructuralHoles.java new file mode 100644 index 0000000000..aec84b9b8c --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/StructuralHoles.java @@ -0,0 +1,310 @@ +/* + * Created on Sep 19, 2005 + * + * Copyright (c) 2005, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.metrics; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Graph; + +/** + * Calculates some of the measures from Burt's text "Structural Holes: + * The Social Structure of Competition". + * + *

        Notes: + *

          + *
        • Each of these measures assumes that each edge has an associated + * non-null weight whose value is accessed through the specified + * Transformer instance. + *
        • Nonexistent edges are treated as edges with weight 0 for purposes + * of edge weight calculations. + *
        + * + *

        Based on code donated by Jasper Voskuilen and + * Diederik van Liere of the Department of Information and Decision Sciences + * at Erasmus University.

        + * + * @author Joshua O'Madadhain + * @author Jasper Voskuilen + * @see "Ronald Burt, Structural Holes: The Social Structure of Competition" + * @author Tom Nelson - converted to jung2 + */ +public class StructuralHoles { + + protected Transformer edge_weight; + protected Graph g; + + /** + * Creates a StructuralHoles instance based on the + * edge weights specified by nev. + */ + public StructuralHoles(Graph graph, Transformer nev) + { + this.g = graph; + this.edge_weight = nev; + } + + /** + * Burt's measure of the effective size of a vertex's network. Essentially, the + * number of neighbors minus the average degree of those in v's neighbor set, + * not counting ties to v. Formally: + *
        +     * effectiveSize(v) = v.degree() - (sum_{u in N(v)} sum_{w in N(u), w !=u,v} p(v,w)*m(u,w))
        +     * 
        + * where + *
          + *
        • N(a) = a.getNeighbors() + *
        • p(v,w) = normalized mutual edge weight of v and w + *
        • m(u,w) = maximum-scaled mutual edge weight of u and w + *
        + * @see #normalizedMutualEdgeWeight(Object, Object) + * @see #maxScaledMutualEdgeWeight(Object, Object) + */ + public double effectiveSize(V v) + { + double result = g.degree(v); + for(V u : g.getNeighbors(v)) { + + for(V w : g.getNeighbors(u)) { + + if (w != v && w != u) + result -= normalizedMutualEdgeWeight(v,w) * + maxScaledMutualEdgeWeight(u,w); + } + } + return result; + } + + /** + * Returns the effective size of v divided by the number of + * alters in v's network. (In other words, + * effectiveSize(v) / v.degree().) + * If v.degree() == 0, returns 0. + */ + public double efficiency(V v) { + double degree = g.degree(v); + + if (degree == 0) + return 0; + else + return effectiveSize(v) / degree; + } + + /** + * Burt's constraint measure (equation 2.4, page 55 of Burt, 1992). Essentially a + * measure of the extent to which v is invested in people who are invested in + * other of v's alters (neighbors). The "constraint" is characterized + * by a lack of primary holes around each neighbor. Formally: + *
        +     * constraint(v) = sum_{w in MP(v), w != v} localConstraint(v,w)
        +     * 
        + * where MP(v) is the subset of v's neighbors that are both predecessors and successors of v. + * @see #localConstraint(Object, Object) + */ + public double constraint(V v) { + double result = 0; + for(V w : g.getSuccessors(v)) { + + if (v != w && g.isPredecessor(v,w)) + { + result += localConstraint(v, w); + } + } + + return result; + } + + + /** + * Calculates the hierarchy value for a given vertex. Returns NaN when + * v's degree is 0, and 1 when v's degree is 1. + * Formally: + *
        +     * hierarchy(v) = (sum_{v in N(v), w != v} s(v,w) * log(s(v,w))}) / (v.degree() * Math.log(v.degree()) 
        +     * 
        + * where + *
          + *
        • N(v) = v.getNeighbors() + *
        • s(v,w) = localConstraint(v,w) / (aggregateConstraint(v) / v.degree()) + *
        + * @see #localConstraint(Object, Object) + * @see #aggregateConstraint(Object) + */ + public double hierarchy(V v) + { + double v_degree = g.degree(v); + + if (v_degree == 0) + return Double.NaN; + if (v_degree == 1) + return 1; + + double v_constraint = aggregateConstraint(v); + + double numerator = 0; + for (V w : g.getNeighbors(v)) { + + if (v != w) + { + double sl_constraint = localConstraint(v, w) / (v_constraint / v_degree); + numerator += sl_constraint * Math.log(sl_constraint); + } + } + + return numerator / (v_degree * Math.log(v_degree)); + } + + /** + * Returns the local constraint on v from a lack of primary holes + * around its neighbor v2. + * Based on Burt's equation 2.4. Formally: + *
        +     * localConstraint(v1, v2) = ( p(v1,v2) + ( sum_{w in N(v)} p(v1,w) * p(w, v2) ) )^2
        +     * 
        + * where + *
          + *
        • N(v) = v.getNeighbors() + *
        • p(v,w) = normalized mutual edge weight of v and w + *
        + * @see #normalizedMutualEdgeWeight(Object, Object) + */ + public double localConstraint(V v1, V v2) + { + double nmew_vw = normalizedMutualEdgeWeight(v1, v2); + double inner_result = 0; + for (V w : g.getNeighbors(v1)) { + + inner_result += normalizedMutualEdgeWeight(v1,w) * + normalizedMutualEdgeWeight(w,v2); + } + return (nmew_vw + inner_result) * (nmew_vw + inner_result); + } + + /** + * The aggregate constraint on v. Based on Burt's equation 2.7. + * Formally: + *
        +     * aggregateConstraint(v) = sum_{w in N(v)} localConstraint(v,w) * O(w)
        +     * 
        + * where + *
          + *
        • N(v) = v.getNeighbors() + *
        • O(w) = organizationalMeasure(w) + *
        + */ + public double aggregateConstraint(V v) + { + double result = 0; + for (V w : g.getNeighbors(v)) { + + result += localConstraint(v, w) * organizationalMeasure(g, w); + } + return result; + } + + /** + * A measure of the organization of individuals within the subgraph + * centered on v. Burt's text suggests that this is + * in some sense a measure of how "replaceable" v is by + * some other element of this subgraph. Should be a number in the + * closed interval [0,1]. + * + *

        This implementation returns 1. Users may wish to override this + * method in order to define their own behavior.

        + */ + protected double organizationalMeasure(Graph g, V v) { + return 1.0; + } + + + /** + * Returns the proportion of v1's network time and energy invested + * in the relationship with v2. Formally: + *
        +     * normalizedMutualEdgeWeight(a,b) = mutual_weight(a,b) / (sum_c mutual_weight(a,c))
        +     * 
        + * Returns 0 if either numerator or denominator = 0, or if v1 == v2. + * @see #mutualWeight(Object, Object) + */ + protected double normalizedMutualEdgeWeight(V v1, V v2) + { + if (v1 == v2) + return 0; + + double numerator = mutualWeight(v1, v2); + + if (numerator == 0) + return 0; + + double denominator = 0; + for (V v : g.getNeighbors(v1)) { + denominator += mutualWeight(v1, v); + } + if (denominator == 0) + return 0; + + return numerator / denominator; + } + + /** + * Returns the weight of the edge from v1 to v2 + * plus the weight of the edge from v2 to v1; + * if either edge does not exist, it is treated as an edge with weight 0. + * Undirected edges are treated as two antiparallel directed edges (that + * is, if there is one undirected edge with weight w connecting + * v1 to v2, the value returned is 2w). + * Ignores parallel edges; if there are any such, one is chosen at random. + * Throws NullPointerException if either edge is + * present but not assigned a weight by the constructor-specified + * NumberEdgeValue. + */ + protected double mutualWeight(V v1, V v2) + { + E e12 = g.findEdge(v1,v2); + E e21 = g.findEdge(v2,v1); + double w12 = (e12 != null ? edge_weight.transform(e12).doubleValue() : 0); + double w21 = (e21 != null ? edge_weight.transform(e21).doubleValue() : 0); + + return w12 + w21; + } + + /** + * The marginal strength of v1's relation with contact vertex2. + * Formally: + *
        +     * normalized_mutual_weight = mutual_weight(a,b) / (max_c mutual_weight(a,c))
        +     * 
        + * Returns 0 if either numerator or denominator is 0, or if v1 == v2. + * @see #mutualWeight(Object, Object) + */ + protected double maxScaledMutualEdgeWeight(V v1, V v2) + { + if (v1 == v2) + return 0; + + double numerator = mutualWeight(v1, v2); + + if (numerator == 0) + return 0; + + double denominator = 0; + for (V w : g.getNeighbors(v1)) { + + if (v2 != w) + denominator = Math.max(numerator, mutualWeight(v1, w)); + } + + if (denominator == 0) + return 0; + + return numerator / denominator; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/TriadicCensus.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/TriadicCensus.java new file mode 100644 index 0000000000..634eb3bcdf --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/TriadicCensus.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.metrics; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.collections15.CollectionUtils; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Graph; + + +/** + * TriadicCensus is a standard social network tool that counts, for each of the + * different possible configurations of three vertices, the number of times + * that that configuration occurs in the given graph. + * This may then be compared to the set of expected counts for this particular + * graph or to an expected sample. This is often used in p* modeling. + *

        + * To use this class, + *

        + * long[] triad_counts = TriadicCensus(dg);
        + * 
        + * where dg is a DirectedGraph. + * ith element of the array (for i in [1,16]) is the number of + * occurrences of the corresponding triad type. + * (The 0th element is not meaningful; this array is effectively 1-based.) + * To get the name of the ith triad (e.g. "003"), + * look at the global constant array c.TRIAD_NAMES[i] + *

        + * Triads are named as + * (number of pairs that are mutually tied) + * (number of pairs that are one-way tied) + * (number of non-tied pairs) + * in the triple. Since there are be only three pairs, there is a finite + * set of these possible triads. + *

        + * In fact, there are exactly 16, conventionally sorted by the number of + * realized edges in the triad: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        Number Configuration Notes
        1003The empty triad
        2012
        3102
        4021D"Down": the directed edges point away
        5021U"Up": the directed edges meet
        6021C"Circle": one in, one out
        7111D"Down": 021D but one edge is mutual
        8111U"Up": 021U but one edge is mutual
        9030T"Transitive": two point to the same vertex
        10030C"Circle": A->B->C->A
        11201
        12120D"Down": 021D but the third edge is mutual
        13120U"Up": 021U but the third edge is mutual
        14120C"Circle": 021C but the third edge is mutual
        15210
        16300The complete
        + *

        + * This implementation takes O( m ), m is the number of edges in the graph. + *
        + * It is based on + * + * A subquadratic triad census algorithm for large sparse networks + * with small maximum degree + * Vladimir Batagelj and Andrej Mrvar, University of Ljubljana + * Published in Social Networks. + * @author Danyel Fisher + * @author Tom Nelson - converted to jung2 + * + */ +public class TriadicCensus { + + // NOTE THAT THIS RETURNS STANDARD 1-16 COUNT! + + // and their types + public static final String[] TRIAD_NAMES = { "N/A", "003", "012", "102", "021D", + "021U", "021C", "111D", "111U", "030T", "030C", "201", "120D", + "120U", "120C", "210", "300" }; + + public static final int MAX_TRIADS = TRIAD_NAMES.length; + + /** + * Returns an array whose ith element (for i in [1,16]) is the number of + * occurrences of the corresponding triad type in g. + * (The 0th element is not meaningful; this array is effectively 1-based.) + * + * @param g + */ + public static long[] getCounts(DirectedGraph g) { + long[] count = new long[MAX_TRIADS]; + + List id = new ArrayList(g.getVertices()); + + // apply algorithm to each edge, one at at time + for (int i_v = 0; i_v < g.getVertexCount(); i_v++) { + V v = id.get(i_v); + for(V u : g.getNeighbors(v)) { + int triType = -1; + if (id.indexOf(u) <= i_v) + continue; + Set neighbors = new HashSet(CollectionUtils.union(g.getNeighbors(u), g.getNeighbors(v))); + neighbors.remove(u); + neighbors.remove(v); + if (g.isSuccessor(v,u) && g.isSuccessor(u,v)) { + triType = 3; + } else { + triType = 2; + } + count[triType] += g.getVertexCount() - neighbors.size() - 2; + for (V w : neighbors) { + if (shouldCount(g, id, u, v, w)) { + count [ triType ( triCode(g, u, v, w) ) ] ++; + } + } + } + } + int sum = 0; + for (int i = 2; i <= 16; i++) { + sum += count[i]; + } + int n = g.getVertexCount(); + count[1] = n * (n-1) * (n-2) / 6 - sum; + return count; + } + + /** + * This is the core of the technique in the paper. Returns an int from 0 to + * 65 based on: WU -> 32 UW -> 16 WV -> 8 VW -> 4 UV -> 2 VU -> 1 + * + */ + public static int triCode(Graph g, V u, V v, V w) { + int i = 0; + i += link(g, v, u ) ? 1 : 0; + i += link(g, u, v ) ? 2 : 0; + i += link(g, v, w ) ? 4 : 0; + i += link(g, w, v ) ? 8 : 0; + i += link(g, u, w ) ? 16 : 0; + i += link(g, w, u ) ? 32 : 0; + return i; + } + + protected static boolean link(Graph g, V a, V b) { + return g.isPredecessor(b, a); + } + + + /** + * Simply returns the triCode. + * @param triCode + * @return the string code associated with the numeric type + */ + public static int triType( int triCode ) { + return codeToType[ triCode ]; + } + + /** + * For debugging purposes, this is copied straight out of the paper which + * means that they refer to triad types 1-16. + */ + protected static final int[] codeToType = { 1, 2, 2, 3, 2, 4, 6, 8, 2, 6, 5, 7, 3, 8, + 7, 11, 2, 6, 4, 8, 5, 9, 9, 13, 6, 10, 9, 14, 7, 14, 12, 15, 2, 5, + 6, 7, 6, 9, 10, 14, 4, 9, 9, 12, 8, 13, 14, 15, 3, 7, 8, 11, 7, 12, + 14, 15, 8, 14, 13, 15, 11, 15, 15, 16 }; + + /** + * Make sure we have a canonical ordering: Returns true if u < w, or v < w < + * u and v doesn't link to w + * + * @param id + * @param u + * @param v + * @param w + * @return true if u < w, or if v < w < u and v doesn't link to w; false otherwise + */ + protected static boolean shouldCount(Graph g, List id, V u, V v, V w) { + int i_u = id.indexOf(u); + int i_w = id.indexOf(w); + if (i_u < i_w) + return true; + int i_v = id.indexOf(v); + if ((i_v < i_w) && (i_w < i_u) && (!g.isNeighbor(w,v))) + return true; + return false; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/package.html new file mode 100644 index 0000000000..ce5144b956 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/metrics/package.html @@ -0,0 +1,27 @@ + + + + + + + +Specialized measures for graph properties. These currently include: + +

          +
        • StructuralHoles: calculates some of Burt's 'structural holes' +measures (e.g. efficiency, hierarchy, constraint). +
        • TriadicCensus: returns counts for each triad type found in a +graph. +
        + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/package.html new file mode 100644 index 0000000000..f9d2e2509e --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/package.html @@ -0,0 +1,61 @@ + + + + + + + +

        Algorithms for graphs and networks.

        + +

        These algorithms are divided into categories as follows: +

          +
        • blockmodel: dividing graph elements (typically vertices) into +equivalence classes, +generally by topological properties (e.g. structural equivalence) +
        • cluster: identifying coherent (not necessarily disjoint) groups of elements +(e.g. weakly connected components, edge betweenness clustering) +
        • filters: removing parts of a graph according to specified criteria +
        • flows: calculating properties relating to network flows +(e.g. max flow/min cut) +
        • generators: creating graphs with certain properties +
        • importance (deprecated): assigning values to vertices/edges +based on topological properties +
        • layout: arrangement of graph elements, generally for visualization +
        • metrics: calculating structural properties (triad census, structural +holes) +
        • scoring: assigning values (denoting significance, influence, +centrality, etc.) to vertices/edges based on topological properties, +e.g. PageRank, HITS, betweenness centrality (replaces "importance", above) +
        • shortestpath: calculation of shortest paths between vertices +
        • util: low-level utility classes used in a variety of algorithms +
        + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorer.java new file mode 100644 index 0000000000..70d677b518 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorer.java @@ -0,0 +1,368 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.util.DelegateToEdgeTransformer; +import edu.uci.ics.jung.algorithms.scoring.util.VEPair; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * An abstract class for algorithms that assign scores to vertices based on iterative methods. + * Generally, any (concrete) subclass will function by creating an instance, and then either calling + * evaluate (if the user wants to iterate until the algorithms is 'done') or + * repeatedly call step (if the user wants to observe the values at each step). + */ +public abstract class AbstractIterativeScorer implements IterativeContext, VertexScorer +{ + /** + * Maximum number of iterations to use before terminating. Defaults to 100. + */ + protected int max_iterations; + + /** + * Minimum change from one step to the next; if all changes are <= tolerance, + * no further updates will occur. + * Defaults to 0.001. + */ + protected double tolerance; + + /** + * The graph on which the calculations are to be made. + */ + protected Hypergraph graph; + + /** + * The total number of iterations used so far. + */ + protected int total_iterations; + + /** + * The edge weights used by this algorithm. + */ + protected Transformer, ? extends Number> edge_weights; + + /** + * Indicates whether the output and current values are in a 'swapped' state. + * Intended for internal use only. + */ + protected boolean output_reversed; + + /** + * The map in which the output values are stored. + */ + private Map output; + + /** + * The map in which the current values are stored. + */ + private Map current_values; + + /** + * A flag representing whether this instance tolerates disconnected graphs. + * Instances that do not accept disconnected graphs may have unexpected behavior + * on disconnected graphs; they are not guaranteed to do an explicit check. + * Defaults to true. + */ + private boolean accept_disconnected_graph; + + + protected boolean hyperedges_are_self_loops = false; + + /** + * Sets the output value for this vertex. + * @param v the vertex whose output value is to be set + * @param value the value to set + */ + protected void setOutputValue(V v, T value) + { + output.put(v, value); + } + + /** + * Gets the output value for this vertex. + * @param v the vertex whose output value is to be retrieved + * @return the output value for this vertex + */ + protected T getOutputValue(V v) + { + return output.get(v); + } + + /** + * Gets the current value for this vertex + * @param v the vertex whose current value is to be retrieved + * @return the current value for this vertex + */ + protected T getCurrentValue(V v) + { + return current_values.get(v); + } + + /** + * Sets the current value for this vertex. + * @param v the vertex whose current value is to be set + * @param value the current value to set + */ + protected void setCurrentValue(V v, T value) + { + current_values.put(v, value); + } + + /** + * The largest change seen so far among all vertex scores. + */ + protected double max_delta; + + /** + * Creates an instance for the specified graph and edge weights. + * @param g the graph for which the instance is to be created + * @param edge_weights the edge weights for this instance + */ + public AbstractIterativeScorer(Hypergraph g, Transformer edge_weights) + { + this.graph = g; + this.max_iterations = 100; + this.tolerance = 0.001; + this.accept_disconnected_graph = true; + setEdgeWeights(edge_weights); + } + + /** + * Creates an instance for the specified graph g. + * NOTE: This constructor does not set the internal + * edge_weights variable. If this variable is used by + * the subclass which invoked this constructor, it must be initialized + * by that subclass. + * @param g the graph for which the instance is to be created + */ + public AbstractIterativeScorer(Hypergraph g) + { + this.graph = g; + this.max_iterations = 100; + this.tolerance = 0.001; + this.accept_disconnected_graph = true; + } + + /** + * Initializes the internal state for this instance. + */ + protected void initialize() + { + this.total_iterations = 0; + this.max_delta = Double.MIN_VALUE; + this.output_reversed = true; + this.current_values = new HashMap(); + this.output = new HashMap(); + } + + /** + * Steps through this scoring algorithm until a termination condition is reached. + */ + public void evaluate() + { + do + step(); + while (!done()); + } + + /** + * Returns true if the total number of iterations is greater than or equal to + * max_iterations + * or if the maximum value change observed is less than tolerance. + */ + public boolean done() + { + return total_iterations >= max_iterations || max_delta < tolerance; + } + + /** + * Performs one step of this algorithm; updates the state (value) for each vertex. + */ + public void step() + { + swapOutputForCurrent(); + + for (V v : graph.getVertices()) + { + double diff = update(v); + updateMaxDelta(v, diff); + } + total_iterations++; + afterStep(); + } + + /** + * + */ + protected void swapOutputForCurrent() + { + Map tmp = output; + output = current_values; + current_values = tmp; + output_reversed = !output_reversed; + } + + /** + * Updates the value for v. + * This is the key + * @param v the vertex whose value is to be updated + * @return + */ + protected abstract double update(V v); + + protected void updateMaxDelta(V v, double diff) + { + max_delta = Math.max(max_delta, diff); + } + + protected void afterStep() {} + + public T getVertexScore(V v) + { + if (!graph.containsVertex(v)) + throw new IllegalArgumentException("Vertex " + v + " not an element of this graph"); + + return output.get(v); + } + + /** + * Returns the maximum number of iterations that this instance will use. + * @return the maximum number of iterations that evaluate will use + * prior to terminating + */ + public int getMaxIterations() + { + return max_iterations; + } + + /** + * Returns the number of iterations that this instance has used so far. + * @return the number of iterations that this instance has used so far + */ + public int getIterations() + { + return total_iterations; + } + + /** + * Sets the maximum number of times that evaluate will call step. + * @param max_iterations the maximum + */ + public void setMaxIterations(int max_iterations) + { + this.max_iterations = max_iterations; + } + + /** + * Gets the size of the largest change (difference between the current and previous values) + * for any vertex that can be tolerated. Once all changes are less than this value, + * evaluate will terminate. + * @return the size of the largest change that evaluate() will permit + */ + public double getTolerance() + { + return tolerance; + } + + /** + * Sets the size of the largest change (difference between the current and previous values) + * for any vertex that can be tolerated. + * @param tolerance the size of the largest change that evaluate() will permit + */ + public void setTolerance(double tolerance) + { + this.tolerance = tolerance; + } + + /** + * Returns the Transformer that this instance uses to associate edge weights with each edge. + * @return the Transformer that associates an edge weight with each edge + */ + public Transformer, ? extends Number> getEdgeWeights() + { + return edge_weights; + } + + /** + * Sets the Transformer that this instance uses to associate edge weights with each edge + * @param edge_weights the Transformer to use to associate an edge weight with each edge + * @see edu.uci.ics.jung.algorithms.scoring.util.UniformDegreeWeight + */ + public void setEdgeWeights(Transformer edge_weights) + { + this.edge_weights = new DelegateToEdgeTransformer(edge_weights); + } + + /** + * Gets the edge weight for e in the context of its (incident) vertex v. + * @param v the vertex incident to e as a context in which the edge weight is to be calculated + * @param e the edge whose weight is to be returned + * @return the edge weight for e in the context of its (incident) vertex v + */ + protected Number getEdgeWeight(V v, E e) + { + return edge_weights.transform(new VEPair(v,e)); + } + + /** + * Collects the 'potential' from v (its current value) if it has no outgoing edges; this + * can then be redistributed among the other vertices as a means of normalization. + * @param v + */ + protected void collectDisappearingPotential(V v) {} + + /** + * Specifies whether this instance should accept vertices with no outgoing edges. + * @param accept true if this instance should accept vertices with no outgoing edges, false otherwise + */ + public void acceptDisconnectedGraph(boolean accept) + { + this.accept_disconnected_graph = accept; + } + + /** + * Returns true if this instance accepts vertices with no outgoing edges, and false otherwise. + * @return true if this instance accepts vertices with no outgoing edges, otherwise false + */ + public boolean isDisconnectedGraphOK() + { + return this.accept_disconnected_graph; + } + + /** + * Specifies whether hyperedges are to be treated as self-loops. If they + * are, then potential will flow along a hyperedge a vertex to itself, + * just as it does to all other vertices incident to that hyperedge. + * @param arg if {@code true}, hyperedges are treated as self-loops + */ + public void setHyperedgesAreSelfLoops(boolean arg) + { + this.hyperedges_are_self_loops = arg; + } + + /** + * Returns the effective number of vertices incident to this edge. If + * the graph is a binary relation or if hyperedges are treated as self-loops, + * the value returned is {@code graph.getIncidentCount(e)}; otherwise it is + * {@code graph.getIncidentCount(e) - 1}. + */ + protected int getAdjustedIncidentCount(E e) + { + return graph.getIncidentCount(e) - (hyperedges_are_self_loops ? 0 : 1); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorerWithPriors.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorerWithPriors.java new file mode 100644 index 0000000000..6883e26384 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorerWithPriors.java @@ -0,0 +1,117 @@ +/* + * Created on Jul 14, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * An abstract class for iterative random-walk-based vertex scoring algorithms + * that have a + * fixed probability, for each vertex, of 'jumping' to that vertex at each + * step in the algorithm (rather than following a link out of that vertex). + * + * @param the vertex type + * @param the edge type + * @param the score type + */ +public abstract class AbstractIterativeScorerWithPriors extends + AbstractIterativeScorer implements VertexScorer +{ + /** + * The prior probability of each vertex being visited on a given + * 'jump' (non-link-following) step. + */ + protected Transformer vertex_priors; + + /** + * The probability of making a 'jump' at each step. + */ + protected double alpha; + + /** + * Creates an instance for the specified graph, edge weights, vertex + * priors, and jump probability. + * @param g the graph whose vertices are to be assigned scores + * @param edge_weights the edge weights to use in the score assignment + * @param vertex_priors the prior probabilities of each vertex being 'jumped' to + * @param alpha the probability of making a 'jump' at each step + */ + public AbstractIterativeScorerWithPriors(Hypergraph g, + Transformer edge_weights, + Transformer vertex_priors, double alpha) + { + super(g, edge_weights); + this.vertex_priors = vertex_priors; + this.alpha = alpha; + initialize(); + } + + /** + * Creates an instance for the specified graph, vertex priors, and jump + * probability, with edge weights specified by the subclass. + * @param g the graph whose vertices are to be assigned scores + * @param vertex_priors the prior probabilities of each vertex being 'jumped' to + * @param alpha the probability of making a 'jump' at each step + */ + public AbstractIterativeScorerWithPriors(Hypergraph g, + Transformer vertex_priors, double alpha) + { + super(g); + this.vertex_priors = vertex_priors; + this.alpha = alpha; + initialize(); + } + + /** + * Initializes the state of this instance. + */ + @Override + public void initialize() + { + super.initialize(); + // initialize output values to priors + // (output and current are swapped before each step(), so current will + // have priors when update()s start happening) + for (V v : graph.getVertices()) + setOutputValue(v, getVertexPrior(v)); + } + + /** + * Returns the prior probability for v. + * @param v the vertex whose prior probability is being queried + * @return the prior probability for v + */ + protected S getVertexPrior(V v) + { + return vertex_priors.transform(v); + } + + /** + * Returns a Transformer which maps each vertex to its prior probability. + * @return a Transformer which maps each vertex to its prior probability + */ + public Transformer getVertexPriors() + { + return vertex_priors; + } + + /** + * Returns the probability of making a 'jump' (non-link-following step). + * @return the probability of making a 'jump' (non-link-following step) + */ + public double getAlpha() + { + return alpha; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/BarycenterScorer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/BarycenterScorer.java new file mode 100644 index 0000000000..1c9c178c55 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/BarycenterScorer.java @@ -0,0 +1,55 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.shortestpath.Distance; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to each vertex according to the sum of its distances to all other vertices. + */ +public class BarycenterScorer extends DistanceCentralityScorer +{ + /** + * Creates an instance with the specified graph and distance metric. + * @param graph the input graph + * @param distance the distance metric to use + */ + public BarycenterScorer(Hypergraph graph, Distance distance) + { + super(graph, distance, false); + } + + /** + * Creates an instance with the specified graph and edge weights. + * Will generate a Distance metric internally based on the edge weights. + * @param graph the input graph + * @param edge_weights the edge weights to use to calculate vertex/vertex distances + */ + public BarycenterScorer(Hypergraph graph, Transformer edge_weights) + { + super(graph, edge_weights, false); + } + + /** + * Creates an instance with the specified graph. + * Will generate a Distance metric internally assuming that the + * graph is unweighted. + * @param graph the input graph + */ + public BarycenterScorer(Hypergraph graph) + { + super(graph, false); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/BetweennessCentrality.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/BetweennessCentrality.java new file mode 100644 index 0000000000..5cfeb1647b --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/BetweennessCentrality.java @@ -0,0 +1,351 @@ +/** + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * Created on Sep 16, 2008 + * + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Stack; + +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.functors.ConstantTransformer; + +import edu.uci.ics.jung.algorithms.util.MapBinaryHeap; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; + +/** + * Computes betweenness centrality for each vertex and edge in the graph. + * + * @see "Ulrik Brandes: A Faster Algorithm for Betweenness Centrality. Journal of Mathematical Sociology 25(2):163-177, 2001." + */ +public class BetweennessCentrality + implements VertexScorer, EdgeScorer +{ + protected Graph graph; + protected Map vertex_scores; + protected Map edge_scores; + protected Map vertex_data; + + /** + * Calculates betweenness scores based on the all-pairs unweighted shortest paths + * in the graph. + * @param graph the graph for which the scores are to be calculated + */ + @SuppressWarnings("unchecked") + public BetweennessCentrality(Graph graph) + { + initialize(graph); + computeBetweenness(new LinkedList(), new ConstantTransformer(1)); + } + + /** + * Calculates betweenness scores based on the all-pairs weighted shortest paths in the + * graph. + * + *

        NOTE: This version of the algorithm may not work correctly on all graphs; we're still + * working out the bugs. Use at your own risk. + * @param graph the graph for which the scores are to be calculated + * @param edge_weights the edge weights to be used in the path length calculations + */ + public BetweennessCentrality(Graph graph, + Transformer edge_weights) + { + // reject negative-weight edges up front + for (E e : graph.getEdges()) + { + double e_weight = edge_weights.transform(e).doubleValue(); + if (e_weight < 0) + throw new IllegalArgumentException(String.format( + "Weight for edge '%s' is < 0: %d", e, e_weight)); + } + + initialize(graph); + computeBetweenness(new MapBinaryHeap(new BetweennessComparator()), + edge_weights); + } + + protected void initialize(Graph graph) + { + this.graph = graph; + this.vertex_scores = new HashMap(); + this.edge_scores = new HashMap(); + this.vertex_data = new HashMap(); + + for (V v : graph.getVertices()) + this.vertex_scores.put(v, 0.0); + + for (E e : graph.getEdges()) + this.edge_scores.put(e, 0.0); + } + + protected void computeBetweenness(Queue queue, + Transformer edge_weights) + { + for (V v : graph.getVertices()) + { + // initialize the betweenness data for this new vertex + for (V s : graph.getVertices()) + this.vertex_data.put(s, new BetweennessData()); + +// if (v.equals(new Integer(0))) +// System.out.println("pause"); + + vertex_data.get(v).numSPs = 1; + vertex_data.get(v).distance = 0; + + Stack stack = new Stack(); +// Buffer queue = new UnboundedFifoBuffer(); +// queue.add(v); + queue.offer(v); + + while (!queue.isEmpty()) + { +// V w = queue.remove(); + V w = queue.poll(); + stack.push(w); + BetweennessData w_data = vertex_data.get(w); + + for (E e : graph.getOutEdges(w)) + { + // TODO (jrtom): change this to getOtherVertices(w, e) + V x = graph.getOpposite(w, e); + if (x.equals(w)) + continue; + double wx_weight = edge_weights.transform(e).doubleValue(); + + +// for(V x : graph.getSuccessors(w)) +// { +// if (x.equals(w)) +// continue; + + // FIXME: the other problem is that I need to + // keep putting the neighbors of things we've just + // discovered in the queue, if they're undiscovered or + // at greater distance. + + // FIXME: this is the problem, right here, I think: + // need to update position in queue if distance changes + // (which can only happen with weighted edges). + // for each outgoing edge e from w, get other end x + // if x not already visited (dist x < 0) + // set x's distance to w's dist + edge weight + // add x to queue; pri in queue is x's dist + // if w's dist + edge weight < x's dist + // update x's dist + // update x in queue (MapBinaryHeap) + // clear x's incoming edge list + // if w's dist + edge weight = x's dist + // add e to x's incoming edge list + + BetweennessData x_data = vertex_data.get(x); + double x_potential_dist = w_data.distance + wx_weight; + + if (x_data.distance < 0) + { +// queue.add(x); +// vertex_data.get(x).distance = vertex_data.get(w).distance + 1; + x_data.distance = x_potential_dist; + queue.offer(x); + } + + // note: + // (1) this can only happen with weighted edges + // (2) x's SP count and incoming edges are updated below + if (x_data.distance > x_potential_dist) + { + x_data.distance = x_potential_dist; + // invalidate previously identified incoming edges + // (we have a new shortest path distance to x) + x_data.incomingEdges.clear(); + // update x's position in queue + ((MapBinaryHeap)queue).update(x); + } +// if (vertex_data.get(x).distance == vertex_data.get(w).distance + 1) + // +// if (x_data.distance == x_potential_dist) +// { +// x_data.numSPs += w_data.numSPs; +//// vertex_data.get(x).predecessors.add(w); +// x_data.incomingEdges.add(e); +// } + } + for (E e: graph.getOutEdges(w)) + { + V x = graph.getOpposite(w, e); + if (x.equals(w)) + continue; + double e_weight = edge_weights.transform(e).doubleValue(); + BetweennessData x_data = vertex_data.get(x); + double x_potential_dist = w_data.distance + e_weight; + if (x_data.distance == x_potential_dist) + { + x_data.numSPs += w_data.numSPs; +// vertex_data.get(x).predecessors.add(w); + x_data.incomingEdges.add(e); + } + } + } + while (!stack.isEmpty()) + { + V x = stack.pop(); + +// for (V w : vertex_data.get(x).predecessors) + for (E e : vertex_data.get(x).incomingEdges) + { + V w = graph.getOpposite(x, e); + double partialDependency = + vertex_data.get(w).numSPs / vertex_data.get(x).numSPs * + (1.0 + vertex_data.get(x).dependency); + vertex_data.get(w).dependency += partialDependency; +// E w_x = graph.findEdge(w, x); +// double w_x_score = edge_scores.get(w_x).doubleValue(); +// w_x_score += partialDependency; +// edge_scores.put(w_x, w_x_score); + double e_score = edge_scores.get(e).doubleValue(); + edge_scores.put(e, e_score + partialDependency); + } + if (!x.equals(v)) + { + double x_score = vertex_scores.get(x).doubleValue(); + x_score += vertex_data.get(x).dependency; + vertex_scores.put(x, x_score); + } + } + } + + if(graph instanceof UndirectedGraph) + { + for (V v : graph.getVertices()) { + double v_score = vertex_scores.get(v).doubleValue(); + v_score /= 2.0; + vertex_scores.put(v, v_score); + } + for (E e : graph.getEdges()) { + double e_score = edge_scores.get(e).doubleValue(); + e_score /= 2.0; + edge_scores.put(e, e_score); + } + } + + vertex_data.clear(); + } + +// protected void computeWeightedBetweenness(Transformer edge_weights) +// { +// for (V v : graph.getVertices()) +// { +// // initialize the betweenness data for this new vertex +// for (V s : graph.getVertices()) +// this.vertex_data.put(s, new BetweennessData()); +// vertex_data.get(v).numSPs = 1; +// vertex_data.get(v).distance = 0; +// +// Stack stack = new Stack(); +//// Buffer queue = new UnboundedFifoBuffer(); +// SortedSet pqueue = new TreeSet(new BetweennessComparator()); +//// queue.add(v); +// pqueue.add(v); +// +//// while (!queue.isEmpty()) +// while (!pqueue.isEmpty()) +// { +//// V w = queue.remove(); +// V w = pqueue.first(); +// pqueue.remove(w); +// stack.push(w); +// +//// for(V x : graph.getSuccessors(w)) +// for (E e : graph.getOutEdges(w)) +// { +// // TODO (jrtom): change this to getOtherVertices(w, e) +// V x = graph.getOpposite(w, e); +// if (x.equals(w)) +// continue; +// double e_weight = edge_weights.transform(e).doubleValue(); +// +// if (vertex_data.get(x).distance < 0) +// { +//// queue.add(x); +// pqueue.add(v); +//// vertex_data.get(x).distance = vertex_data.get(w).distance + 1; +// vertex_data.get(x).distance = +// vertex_data.get(w).distance + e_weight; +// } +// +//// if (vertex_data.get(x).distance == vertex_data.get(w).distance + 1) +// if (vertex_data.get(x).distance == +// vertex_data.get(w).distance + e_weight) +// { +// vertex_data.get(x).numSPs += vertex_data.get(w).numSPs; +// vertex_data.get(x).predecessors.add(w); +// } +// } +// } +// updateScores(v, stack); +// } +// +// if(graph instanceof UndirectedGraph) +// adjustUndirectedScores(); +// +// vertex_data.clear(); +// } + + public Double getVertexScore(V v) + { + return vertex_scores.get(v); + } + + public Double getEdgeScore(E e) + { + return edge_scores.get(e); + } + + private class BetweennessData + { + double distance; + double numSPs; +// List predecessors; + List incomingEdges; + double dependency; + + BetweennessData() + { + distance = -1; + numSPs = 0; +// predecessors = new ArrayList(); + incomingEdges = new ArrayList(); + dependency = 0; + } + + @Override + public String toString() + { + return "[d:" + distance + ", sp:" + numSPs + + ", p:" + incomingEdges + ", d:" + dependency + "]\n"; +// ", p:" + predecessors + ", d:" + dependency + "]\n"; + } + } + + private class BetweennessComparator implements Comparator + { + public int compare(V v1, V v2) + { + return vertex_data.get(v1).distance > vertex_data.get(v2).distance ? 1 : -1; + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/ClosenessCentrality.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/ClosenessCentrality.java new file mode 100644 index 0000000000..d64f01ed41 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/ClosenessCentrality.java @@ -0,0 +1,55 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.shortestpath.Distance; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to each vertex based on the mean distance to each other vertex. + * + * @author Joshua O'Madadhain + */ +public class ClosenessCentrality extends DistanceCentralityScorer +{ + + /** + * Creates an instance using the specified vertex/vertex distance metric. + * @param graph the input + * @param distance the vertex/vertex distance metric. + */ + public ClosenessCentrality(Hypergraph graph, Distance distance) + { + super(graph, distance, true); + } + + /** + * Creates an instance which measures distance using the specified edge weights. + * @param graph the input graph + * @param edge_weights the edge weights to be used to determine vertex/vertex distances + */ + public ClosenessCentrality(Hypergraph graph, Transformer edge_weights) + { + super(graph, edge_weights, true); + } + + /** + * Creates an instance which measures distance on the graph without edge weights. + * @param graph + */ + public ClosenessCentrality(Hypergraph graph) + { + super(graph, true); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/DegreeScorer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/DegreeScorer.java new file mode 100644 index 0000000000..2ec3148104 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/DegreeScorer.java @@ -0,0 +1,45 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns a score to each vertex equal to its degree. + * + * @param the vertex type + */ +public class DegreeScorer implements VertexScorer +{ + /** + * The graph for which scores are to be generated. + */ + protected Hypergraph graph; + + /** + * Creates an instance for the specified graph. + * @param graph the input graph + */ + public DegreeScorer(Hypergraph graph) + { + this.graph = graph; + } + + /** + * Returns the degree of the vertex. + * @return the degree of the vertex + */ + public Integer getVertexScore(V v) + { + return graph.degree(v); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/DistanceCentralityScorer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/DistanceCentralityScorer.java new file mode 100644 index 0000000000..16dd86219d --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/DistanceCentralityScorer.java @@ -0,0 +1,249 @@ +/* + * Created on Jul 10, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.shortestpath.DijkstraDistance; +import edu.uci.ics.jung.algorithms.shortestpath.Distance; +import edu.uci.ics.jung.algorithms.shortestpath.UnweightedShortestPath; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to vertices based on their distances to each other vertex + * in the graph. + * + * This class optionally normalizes its results based on the value of its + * 'averaging' constructor parameter. If it is true, + * then the value returned for vertex v is 1 / (_average_ distance from v to all other vertices); + * this is sometimes called closeness centrality. + * If it is false, then the value returned is 1 / (_total_ distance from + * v to all other vertices); this is sometimes referred to as barycenter centrality. + * (If the average/total distance is 0, the value returned is {@code Double.POSITIVE_INFINITY}.) + * + * @see BarycenterScorer + * @see ClosenessCentrality + */ +public class DistanceCentralityScorer implements VertexScorer +{ + /** + * The graph on which the vertex scores are to be calculated. + */ + protected Hypergraph graph; + + /** + * The metric to use for specifying the distance between pairs of vertices. + */ + protected Distance distance; + + /** + * The cache for the output results. Null encodes "not yet calculated", + * < 0 encodes "no such distance exists". + */ + protected Map output; + + /** + * Specifies whether the values returned are the sum of the v-distances + * or the mean v-distance. + */ + protected boolean averaging; + + /** + * Specifies whether, for a vertex v with missing (null) distances, + * v's score should ignore the missing values or be set to 'null'. + * Defaults to 'true'. + */ + protected boolean ignore_missing; + + /** + * Specifies whether the values returned should ignore self-distances + * (distances from v to itself). + * Defaults to 'true'. + */ + protected boolean ignore_self_distances; + + /** + * Creates an instance with the specified graph, distance metric, and + * averaging behavior. + * + * @param graph The graph on which the vertex scores are to be calculated. + * @param distance The metric to use for specifying the distance between + * pairs of vertices. + * @param averaging Specifies whether the values returned is the sum of all + * v-distances or the mean v-distance. + * @param ignore_missing Specifies whether scores for missing distances + * are to ignore missing distances or be set to null. + * @param ignore_self_distances Specifies whether distances from a vertex + * to itself should be included in its score. + */ + public DistanceCentralityScorer(Hypergraph graph, Distance distance, + boolean averaging, boolean ignore_missing, + boolean ignore_self_distances) + { + this.graph = graph; + this.distance = distance; + this.averaging = averaging; + this.ignore_missing = ignore_missing; + this.ignore_self_distances = ignore_self_distances; + this.output = new HashMap(); + } + + /** + * Equivalent to this(graph, distance, averaging, true, true). + * + * @param graph The graph on which the vertex scores are to be calculated. + * @param distance The metric to use for specifying the distance between + * pairs of vertices. + * @param averaging Specifies whether the values returned is the sum of all + * v-distances or the mean v-distance. + */ + public DistanceCentralityScorer(Hypergraph graph, Distance distance, + boolean averaging) + { + this(graph, distance, averaging, true, true); + } + + /** + * Creates an instance with the specified graph and averaging behavior + * whose vertex distances are calculated based on the specified edge + * weights. + * + * @param graph The graph on which the vertex scores are to be + * calculated. + * @param edge_weights The edge weights to use for specifying the distance + * between pairs of vertices. + * @param averaging Specifies whether the values returned is the sum of + * all v-distances or the mean v-distance. + * @param ignore_missing Specifies whether scores for missing distances + * are to ignore missing distances or be set to null. + * @param ignore_self_distances Specifies whether distances from a vertex + * to itself should be included in its score. + */ + public DistanceCentralityScorer(Hypergraph graph, + Transformer edge_weights, boolean averaging, + boolean ignore_missing, boolean ignore_self_distances) + { + this(graph, new DijkstraDistance(graph, edge_weights), averaging, + ignore_missing, ignore_self_distances); + } + + /** + * Equivalent to this(graph, edge_weights, averaging, true, true). + * @param graph The graph on which the vertex scores are to be + * calculated. + * @param edge_weights The edge weights to use for specifying the distance + * between pairs of vertices. + * @param averaging Specifies whether the values returned is the sum of + * all v-distances or the mean v-distance. + */ + public DistanceCentralityScorer(Hypergraph graph, + Transformer edge_weights, boolean averaging) + { + this(graph, new DijkstraDistance(graph, edge_weights), averaging, + true, true); + } + + /** + * Creates an instance with the specified graph and averaging behavior + * whose vertex distances are calculated on the unweighted graph. + * + * @param graph The graph on which the vertex scores are to be + * calculated. + * @param averaging Specifies whether the values returned is the sum of + * all v-distances or the mean v-distance. + * @param ignore_missing Specifies whether scores for missing distances + * are to ignore missing distances or be set to null. + * @param ignore_self_distances Specifies whether distances from a vertex + * to itself should be included in its score. + */ + public DistanceCentralityScorer(Hypergraph graph, boolean averaging, + boolean ignore_missing, boolean ignore_self_distances) + { + this(graph, new UnweightedShortestPath(graph), averaging, + ignore_missing, ignore_self_distances); + } + + /** + * Equivalent to this(graph, averaging, true, true). + * @param graph The graph on which the vertex scores are to be + * calculated. + * @param averaging Specifies whether the values returned is the sum of + * all v-distances or the mean v-distance. + */ + public DistanceCentralityScorer(Hypergraph graph, boolean averaging) + { + this(graph, new UnweightedShortestPath(graph), averaging, true, true); + } + + /** + * Calculates the score for the specified vertex. Returns {@code null} if + * there are missing distances and such are not ignored by this instance. + */ + public Double getVertexScore(V v) + { + Double value = output.get(v); + if (value != null) + { + if (value < 0) + return null; + return value; + } + + Map v_distances = new HashMap(distance.getDistanceMap(v)); + if (ignore_self_distances) + v_distances.remove(v); + + // if we don't ignore missing distances and there aren't enough + // distances, output null (shortcut) + if (!ignore_missing) + { + int num_dests = graph.getVertexCount() - + (ignore_self_distances ? 1 : 0); + if (v_distances.size() != num_dests) + { + output.put(v, -1.0); + return null; + } + } + + Double sum = 0.0; + for (V w : graph.getVertices()) + { + if (w.equals(v) && ignore_self_distances) + continue; + Number w_distance = v_distances.get(w); + if (w_distance == null) + if (ignore_missing) + continue; + else + { + output.put(v, -1.0); + return null; + } + else + sum += w_distance.doubleValue(); + } + value = sum; + if (averaging) + value /= v_distances.size(); + + double score = value == 0 ? + Double.POSITIVE_INFINITY : + 1.0 / value; + output.put(v, score); + + return score; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/EdgeScorer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/EdgeScorer.java new file mode 100644 index 0000000000..7e648746d0 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/EdgeScorer.java @@ -0,0 +1,28 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + + +/** + * An interface for algorithms that assign scores to edges. + * + * @param the edge type + * @param the score type + */ +public interface EdgeScorer +{ + /** + * Returns the algorithm's score for this edge. + * @return the algorithm's score for this edge + */ + public S getEdgeScore(E e); +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/EigenvectorCentrality.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/EigenvectorCentrality.java new file mode 100644 index 0000000000..87d7f3ae10 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/EigenvectorCentrality.java @@ -0,0 +1,52 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Calculates eigenvector centrality for each vertex in the graph. + * The 'eigenvector centrality' for a vertex is defined as the fraction of + * time that a random walk(er) will spend at that vertex over an infinite + * time horizon. + * Assumes that the graph is strongly connected. + */ +public class EigenvectorCentrality extends PageRank +{ + /** + * Creates an instance with the specified graph and edge weights. + * The outgoing edge weights for each edge must sum to 1. + * (See UniformDegreeWeight for one way to handle this for + * undirected graphs.) + * @param graph the graph for which the centrality is to be calculated + * @param edge_weights the edge weights + */ + public EigenvectorCentrality(Hypergraph graph, + Transformer edge_weights) + { + super(graph, edge_weights, 0); + acceptDisconnectedGraph(false); + } + + /** + * Creates an instance with the specified graph and default edge weights. + * (Default edge weights: UniformDegreeWeight.) + * @param graph the graph for which the centrality is to be calculated. + */ + public EigenvectorCentrality(Hypergraph graph) + { + super(graph, 0); + acceptDisconnectedGraph(false); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITS.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITS.java new file mode 100644 index 0000000000..b1b4f42899 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITS.java @@ -0,0 +1,145 @@ +/* + * Created on Jul 15, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.Graph; + +import org.apache.commons.collections15.Transformer; + +/** + * Assigns hub and authority scores to each vertex depending on the topology of + * the network. The essential idea is that a vertex is a hub to the extent + * that it links to authoritative vertices, and is an authority to the extent + * that it links to 'hub' vertices. + * + *

        The classic HITS algorithm essentially proceeds as follows: + *

        + * assign equal initial hub and authority values to each vertex
        + * repeat
        + *   for each vertex w:
        + *     w.hub = sum over successors x of x.authority
        + *     w.authority = sum over predecessors v of v.hub
        + *   normalize hub and authority scores so that the sum of the squares of each = 1
        + * until scores converge
        + * 
        + * + * HITS is somewhat different from random walk/eigenvector-based algorithms + * such as PageRank in that: + *
          + *
        • there are two mutually recursive scores being calculated, rather than + * a single value + *
        • the edge weights are effectively all 1, i.e., they can't be interpreted + * as transition probabilities. This means that the more inlinks and outlinks + * that a vertex has, the better, since adding an inlink (or outlink) does + * not dilute the influence of the other inlinks (or outlinks) as in + * random walk-based algorithms. + *
        • the scores cannot be interpreted as posterior probabilities (due to the different + * normalization) + *
        + * + * This implementation has the classic behavior by default. However, it has + * been generalized somewhat so that it can act in a more "PageRank-like" fashion: + *
          + *
        • this implementation has an optional 'random jump probability' parameter analogous + * to the 'alpha' parameter used by PageRank. Varying this value between 0 and 1 + * allows the user to vary between the classic HITS behavior and one in which the + * scores are smoothed to a uniform distribution. + * The default value for this parameter is 0 (no random jumps possible). + *
        • the edge weights can be set to anything the user likes, and in + * particular they can be set up (e.g. using UniformDegreeWeight) + * so that the weights of the relevant edges incident to a vertex sum to 1. + *
        • The vertex score normalization has been factored into its own method + * so that it can be overridden by a subclass. Thus, for example, + * since the vertices' values are set to sum to 1 initially, if the weights of the + * relevant edges incident to a vertex sum to 1, then the vertices' values + * will continue to sum to 1 if the "sum-of-squares" normalization code + * is overridden to a no-op. (Other normalization methods may also be employed.) + *
        + * + * @param the vertex type + * @param the edge type + * + * @see "'Authoritative sources in a hyperlinked environment' by Jon Kleinberg, 1997" + */ +public class HITS extends HITSWithPriors +{ + + /** + * Creates an instance for the specified graph, edge weights, and alpha + * (random jump probability) parameter. + * @param g the input graph + * @param edge_weights the weights to use for each edge + * @param alpha the probability of a hub giving some authority to all vertices, + * and of an authority increasing the score of all hubs (not just those connected + * via links) + */ + public HITS(Graph g, Transformer edge_weights, double alpha) + { + super(g, edge_weights, ScoringUtils.getHITSUniformRootPrior(g.getVertices()), alpha); + } + + /** + * Creates an instance for the specified graph and alpha (random jump probability) + * parameter. The edge weights are all set to 1. + * @param g the input graph + * @param alpha the probability of a hub giving some authority to all vertices, + * and of an authority increasing the score of all hubs (not just those connected + * via links) + */ + public HITS(Graph g, double alpha) + { + super(g, ScoringUtils.getHITSUniformRootPrior(g.getVertices()), alpha); + } + + /** + * Creates an instance for the specified graph. The edge weights are all set to 1 + * and alpha is set to 0. + * @param g the input graph + */ + public HITS(Graph g) + { + this(g, 0.0); + } + + + /** + * Maintains hub and authority score information for a vertex. + */ + public static class Scores + { + /** + * The hub score for a vertex. + */ + public double hub; + + /** + * The authority score for a vertex. + */ + public double authority; + + /** + * Creates an instance with the specified hub and authority score. + */ + public Scores(double hub, double authority) + { + this.hub = hub; + this.authority = authority; + } + + @Override + public String toString() + { + return String.format("[h:%.4f,a:%.4f]", this.hub, this.authority); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITSWithPriors.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITSWithPriors.java new file mode 100644 index 0000000000..51ba71903e --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITSWithPriors.java @@ -0,0 +1,200 @@ +/* + * Created on Jul 14, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.functors.ConstantTransformer; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * A generalization of HITS that permits non-uniformly-distributed random jumps. + * The 'vertex_priors' (that is, prior probabilities for each vertex) may be + * thought of as the fraction of the total 'potential' (hub or authority score) + * that is assigned to that vertex out of the portion that is assigned according + * to random jumps. + * + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + */ +public class HITSWithPriors + extends AbstractIterativeScorerWithPriors +{ + /** + * The sum of the potential, at each step, associated with vertices with no outedges (authority) + * or no inedges (hub). + */ + protected HITS.Scores disappearing_potential; + + /** + * Creates an instance for the specified graph, edge weights, vertex prior probabilities, + * and random jump probability (alpha). + * @param g the input graph + * @param edge_weights the edge weights + * @param vertex_priors the prior probability for each vertex + * @param alpha the probability of a random jump at each step + */ + public HITSWithPriors(Hypergraph g, + Transformer edge_weights, + Transformer vertex_priors, double alpha) + { + super(g, edge_weights, vertex_priors, alpha); + disappearing_potential = new HITS.Scores(0,0); + } + + /** + * Creates an instance for the specified graph, vertex priors, and random + * jump probability (alpha). The edge weights default to 1.0. + * @param g the input graph + * @param vertex_priors the prior probability for each vertex + * @param alpha the probability of a random jump at each step + */ + @SuppressWarnings("unchecked") + public HITSWithPriors(Hypergraph g, + Transformer vertex_priors, double alpha) + { + super(g, new ConstantTransformer(1.0), vertex_priors, alpha); + disappearing_potential = new HITS.Scores(0,0); + } + + /** + * Updates the value for this vertex. + */ + @Override + protected double update(V v) + { + collectDisappearingPotential(v); + + double v_auth = 0; + for (E e : graph.getInEdges(v)) + { + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + v_auth += (getCurrentValue(w).hub * + getEdgeWeight(w,e).doubleValue() / incident_count); + } +// V w = graph.getOpposite(v, e); +// auth += (getCurrentValue(w).hub * getEdgeWeight(w, e).doubleValue()); + } + + double v_hub = 0; + for (E e : graph.getOutEdges(v)) + { + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + v_hub += (getCurrentValue(w).authority * + getEdgeWeight(w,e).doubleValue() / incident_count); + } +// V x = graph.getOpposite(v,e); +// hub += (getCurrentValue(x).authority * getEdgeWeight(x, e).doubleValue()); + } + + // modify total_input according to alpha + if (alpha > 0) + { + v_auth = v_auth * (1 - alpha) + getVertexPrior(v).authority * alpha; + v_hub = v_hub * (1 - alpha) + getVertexPrior(v).hub * alpha; + } + setOutputValue(v, new HITS.Scores(v_hub, v_auth)); + + return Math.max(Math.abs(getCurrentValue(v).hub - v_hub), + Math.abs(getCurrentValue(v).authority - v_auth)); + } + + /** + * Code which is executed after each step. In this case, deals with the + * 'disappearing potential', normalizes the scores, and then calls + * super.afterStep(). + * @see #collectDisappearingPotential(Object) + */ + @Override + protected void afterStep() + { + if (disappearing_potential.hub > 0 || disappearing_potential.authority > 0) + { + for (V v : graph.getVertices()) + { + double new_hub = getOutputValue(v).hub + + (1 - alpha) * (disappearing_potential.hub * getVertexPrior(v).hub); + double new_auth = getOutputValue(v).authority + + (1 - alpha) * (disappearing_potential.authority * getVertexPrior(v).authority); + setOutputValue(v, new HITS.Scores(new_hub, new_auth)); + } + disappearing_potential.hub = 0; + disappearing_potential.authority = 0; + } + + normalizeScores(); + + super.afterStep(); + } + + /** + * Normalizes scores so that sum of their squares = 1. + * This method may be overridden so as to yield different + * normalizations. + */ + protected void normalizeScores() { + double hub_ssum = 0; + double auth_ssum = 0; + for (V v : graph.getVertices()) + { + double hub_val = getOutputValue(v).hub; + double auth_val = getOutputValue(v).authority; + hub_ssum += (hub_val * hub_val); + auth_ssum += (auth_val * auth_val); + } + + hub_ssum = Math.sqrt(hub_ssum); + auth_ssum = Math.sqrt(auth_ssum); + + for (V v : graph.getVertices()) + { + HITS.Scores values = getOutputValue(v); + setOutputValue(v, new HITS.Scores( + values.hub / hub_ssum, + values.authority / auth_ssum)); + } + } + + /** + * Collects the "disappearing potential" associated with vertices that have either + * no incoming edges, no outgoing edges, or both. Vertices that have no incoming edges + * do not directly contribute to the hub scores of other vertices; similarly, vertices + * that have no outgoing edges do not directly contribute to the authority scores of + * other vertices. These values are collected at each step and then distributed across all vertices + * as a part of the normalization process. (This process is not required for, and does + * not affect, the 'sum-of-squares'-style normalization.) + */ + @Override + protected void collectDisappearingPotential(V v) + { + if (graph.outDegree(v) == 0) + { + if (isDisconnectedGraphOK()) + disappearing_potential.hub += getCurrentValue(v).authority; + else + throw new IllegalArgumentException("Outdegree of " + v + " must be > 0"); + } + if (graph.inDegree(v) == 0) + { + if (isDisconnectedGraphOK()) + disappearing_potential.authority += getCurrentValue(v).hub; + else + throw new IllegalArgumentException("Indegree of " + v + " must be > 0"); + } + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/KStepMarkov.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/KStepMarkov.java new file mode 100644 index 0000000000..e640b1b3f3 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/KStepMarkov.java @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * Created on Aug 22, 2008 + * + */ +package edu.uci.ics.jung.algorithms.scoring; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * A special case of {@code PageRankWithPriors} in which the final scores + * represent a probability distribution over position assuming a random (Markovian) + * walk of exactly k steps, based on the initial distribution specified by the priors. + * + *

        NOTE: The version of {@code KStepMarkov} in {@code algorithms.importance} + * (and in JUNG 1.x) is believed to be incorrect: rather than returning + * a score which represents a probability distribution over position assuming + * a k-step random walk, it returns a score which represents the sum over all steps + * of the probability for each step. If you want that behavior, set the + * 'cumulative' flag as follows before calling {@code evaluate()}: + *

        + *     KStepMarkov ksm = new KStepMarkov(...);
        + *     ksm.setCumulative(true);
        + *     ksm.evaluate();
        + * 
        + * + * By default, the 'cumulative' flag is set to false. + * + * NOTE: THIS CLASS IS NOT YET COMPLETE. USE AT YOUR OWN RISK. (The original behavior + * is captured by the version still available in {@code algorithms.importance}.) + * + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + * @see PageRank + * @see PageRankWithPriors + */ +public class KStepMarkov extends PageRankWithPriors +{ + private boolean cumulative; + + /** + * Creates an instance based on the specified graph, edge weights, vertex + * priors (initial scores), and number of steps to take. + * @param graph the input graph + * @param edge_weights the edge weights (transition probabilities) + * @param vertex_priors the initial probability distribution (score assignment) + * @param steps the number of times that {@code step()} will be called by {@code evaluate} + */ + public KStepMarkov(Hypergraph graph, Transformer edge_weights, + Transformer vertex_priors, int steps) + { + super(graph, edge_weights, vertex_priors, 0); + initialize(steps); + } + + /** + * Creates an instance based on the specified graph, vertex + * priors (initial scores), and number of steps to take. The edge + * weights (transition probabilities) are set to default values (a uniform + * distribution over all outgoing edges). + * @param graph the input graph + * @param vertex_priors the initial probability distribution (score assignment) + * @param steps the number of times that {@code step()} will be called by {@code evaluate} + */ + public KStepMarkov(Hypergraph graph, Transformer vertex_priors, int steps) + { + super(graph, vertex_priors, 0); + initialize(steps); + } + + /** + * Creates an instance based on the specified graph and number of steps to + * take. The edge weights (transition probabilities) and vertex initial scores + * (prior probabilities) are set to default values (a uniform + * distribution over all outgoing edges, and a uniform distribution over + * all vertices, respectively). + * @param graph the input graph + * @param steps the number of times that {@code step()} will be called by {@code evaluate} + */ + public KStepMarkov(Hypergraph graph, int steps) + { + super(graph, ScoringUtils.getUniformRootPrior(graph.getVertices()), 0); + initialize(steps); + } + + private void initialize(int steps) + { + this.acceptDisconnectedGraph(false); + + if (steps <= 0) + throw new IllegalArgumentException("Number of steps must be > 0"); + + this.max_iterations = steps; + this.tolerance = -1.0; + + this.cumulative = false; + } + + /** + * Specifies whether this instance should assign a score to each vertex + * based on the + * @param cumulative + */ + public void setCumulative(boolean cumulative) + { + this.cumulative = cumulative; + } + + /** + * Updates the value for this vertex. Called by step(). + */ + @Override + public double update(V v) + { + if (!cumulative) + return super.update(v); + + collectDisappearingPotential(v); + + double v_input = 0; + for (E e : graph.getInEdges(v)) + { + // For graphs, the code below is equivalent to +// V w = graph.getOpposite(v, e); +// total_input += (getCurrentValue(w) * getEdgeWeight(w,e).doubleValue()); + // For hypergraphs, this divides the potential coming from w + // by the number of vertices in the connecting edge e. + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + v_input += (getCurrentValue(w) * + getEdgeWeight(w,e).doubleValue() / incident_count); + } + } + + // modify total_input according to alpha + double new_value = alpha > 0 ? + v_input * (1 - alpha) + getVertexPrior(v) * alpha : + v_input; + setOutputValue(v, new_value + getCurrentValue(v)); + + // FIXME: DO WE NEED TO CHANGE HOW DISAPPEARING IS COUNTED? NORMALIZE? + + return Math.abs(getCurrentValue(v) - new_value); + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRank.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRank.java new file mode 100644 index 0000000000..ca7266d58f --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRank.java @@ -0,0 +1,70 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to each vertex according to the PageRank algorithm. + * + *

        PageRank is an eigenvector-based algorithm. The score for a given vertex may be thought of + * as the fraction of time spent 'visiting' that vertex (measured over all time) + * in a random walk over the vertices (following outgoing edges from each vertex). + * PageRank modifies this random walk by adding to the model a probability (specified as 'alpha' + * in the constructor) of jumping to any vertex. If alpha is 0, this is equivalent to the + * eigenvector centrality algorithm; if alpha is 1, all vertices will receive the same score + * (1/|V|). Thus, alpha acts as a sort of score smoothing parameter. + * + *

        The original algorithm assumed that, for a given vertex, the probability of following any + * outgoing edge was the same; this is the default if edge weights are not specified. + * This implementation generalizes the original by permitting + * the user to specify edge weights; in order to maintain the original semantics, however, + * the weights on the outgoing edges for a given vertex must represent transition probabilities; + * that is, they must sum to 1. + * + *

        If a vertex has no outgoing edges, then the probability of taking a random jump from that + * vertex is (by default) effectively 1. If the user wishes to instead throw an exception when this happens, + * call acceptDisconnectedGraph(false) on this instance. + * + *

        Typical values for alpha (according to the original paper) are in the range [0.1, 0.2] + * but may be any value between 0 and 1 inclusive. + * + * @see "The Anatomy of a Large-Scale Hypertextual Web Search Engine by L. Page and S. Brin, 1999" + */ +public class PageRank extends PageRankWithPriors +{ + + /** + * Creates an instance for the specified graph, edge weights, and random jump probability. + * @param graph the input graph + * @param edge_weight the edge weights (transition probabilities) + * @param alpha the probability of taking a random jump to an arbitrary vertex + */ + public PageRank(Hypergraph graph, Transformer edge_weight, double alpha) + { + super(graph, edge_weight, ScoringUtils.getUniformRootPrior(graph.getVertices()), alpha); + } + + /** + * Creates an instance for the specified graph and random jump probability; the probability + * of following any outgoing edge from a given vertex is the same. + * @param graph the input graph + * @param alpha the probability of taking a random jump to an arbitrary vertex + */ + public PageRank(Hypergraph graph, double alpha) + { + super(graph, ScoringUtils.getUniformRootPrior(graph.getVertices()), alpha); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRankWithPriors.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRankWithPriors.java new file mode 100644 index 0000000000..717d5eafe1 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRankWithPriors.java @@ -0,0 +1,142 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.util.UniformDegreeWeight; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * A generalization of PageRank that permits non-uniformly-distributed random jumps. + * The 'vertex_priors' (that is, prior probabilities for each vertex) may be + * thought of as the fraction of the total 'potential' that is assigned to that + * vertex at each step out of the portion that is assigned according + * to random jumps (this portion is specified by 'alpha'). + * + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + * @see PageRank + */ +public class PageRankWithPriors + extends AbstractIterativeScorerWithPriors +{ + /** + * Maintains the amount of potential associated with vertices with no out-edges. + */ + protected double disappearing_potential = 0.0; + + /** + * Creates an instance with the specified graph, edge weights, vertex priors, and + * 'random jump' probability (alpha). + * @param graph the input graph + * @param edge_weights the edge weights, denoting transition probabilities from source to destination + * @param vertex_priors the prior probabilities for each vertex + * @param alpha the probability of executing a 'random jump' at each step + */ + public PageRankWithPriors(Hypergraph graph, + Transformer edge_weights, + Transformer vertex_priors, double alpha) + { + super(graph, edge_weights, vertex_priors, alpha); + } + + /** + * Creates an instance with the specified graph, vertex priors, and + * 'random jump' probability (alpha). The outgoing edge weights for each + * vertex will be equal and sum to 1. + * @param graph the input graph + * @param vertex_priors the prior probabilities for each vertex + * @param alpha the probability of executing a 'random jump' at each step + */ + public PageRankWithPriors(Hypergraph graph, + Transformer vertex_priors, double alpha) + { + super(graph, vertex_priors, alpha); + this.edge_weights = new UniformDegreeWeight(graph); + } + + /** + * Updates the value for this vertex. Called by step(). + */ + @Override + public double update(V v) + { + collectDisappearingPotential(v); + + double v_input = 0; + for (E e : graph.getInEdges(v)) + { + // For graphs, the code below is equivalent to +// V w = graph.getOpposite(v, e); +// total_input += (getCurrentValue(w) * getEdgeWeight(w,e).doubleValue()); + // For hypergraphs, this divides the potential coming from w + // by the number of vertices in the connecting edge e. + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + v_input += (getCurrentValue(w) * + getEdgeWeight(w,e).doubleValue() / incident_count); + } + } + + // modify total_input according to alpha + double new_value = alpha > 0 ? + v_input * (1 - alpha) + getVertexPrior(v) * alpha : + v_input; + setOutputValue(v, new_value); + + return Math.abs(getCurrentValue(v) - new_value); + } + + /** + * Cleans up after each step. In this case that involves allocating the disappearing + * potential (thus maintaining normalization of the scores) according to the vertex + * probability priors, and then calling + * super.afterStep. + */ + @Override + protected void afterStep() + { + // distribute disappearing potential according to priors + if (disappearing_potential > 0) + { + for (V v : graph.getVertices()) + { + setOutputValue(v, getOutputValue(v) + + (1 - alpha) * (disappearing_potential * getVertexPrior(v))); + } + disappearing_potential = 0; + } + + super.afterStep(); + } + + /** + * Collects the "disappearing potential" associated with vertices that have + * no outgoing edges. Vertices that have no outgoing edges do not directly + * contribute to the scores of other vertices. These values are collected + * at each step and then distributed across all vertices + * as a part of the normalization process. + */ + @Override + protected void collectDisappearingPotential(V v) + { + if (graph.outDegree(v) == 0) + { + if (isDisconnectedGraphOK()) + disappearing_potential += getCurrentValue(v); + else + throw new IllegalArgumentException("Outdegree of " + v + " must be > 0"); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/VertexScorer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/VertexScorer.java new file mode 100644 index 0000000000..610de6b5a6 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/VertexScorer.java @@ -0,0 +1,28 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + + +/** + * An interface for algorithms that assign scores to vertices. + * + * @param the vertex type + * @param the score type + */ +public interface VertexScorer +{ + /** + * Returns the algorithm's score for this vertex. + * @return the algorithm's score for this vertex + */ + public S getVertexScore(V v); +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/VoltageScorer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/VoltageScorer.java new file mode 100644 index 0000000000..f05b911091 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/VoltageScorer.java @@ -0,0 +1,250 @@ +/* + * Created on Jul 15, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.util.UniformDegreeWeight; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to vertices according to their 'voltage' in an approximate + * solution to the Kirchoff equations. This is accomplished by tying "source" + * vertices to specified positive voltages, "sink" vertices to 0 V, and + * iteratively updating the voltage of each other vertex to the (weighted) + * average of the voltages of its neighbors. + * + *

        The resultant voltages will all be in the range [0, max] + * where max is the largest voltage of any source vertex (in the + * absence of negative source voltages; see below). + * + *

        A few notes about this algorithm's interpretation of the graph data: + *

          + *
        • Higher edge weights are interpreted as indicative of greater + * influence/effect than lower edge weights. + *
        • Negative edge weights (and negative "source" voltages) invalidate + * the interpretation of the resultant values as voltages. However, this + * algorithm will not reject graphs with negative edge weights or source voltages. + *
        • Parallel edges are equivalent to a single edge whose weight is the + * sum of the weights on the parallel edges. + *
        • Current flows along undirected edges in both directions, + * but only flows along directed edges in the direction of the edge. + *
        + *

        + */ +public class VoltageScorer extends AbstractIterativeScorer + implements VertexScorer +{ + protected Map source_voltages; + protected Collection sinks; + + /** + * Creates an instance with the specified graph, edge weights, source voltages, + * and sinks. + * @param g the input graph + * @param edge_weights the edge weights, representing conductivity + * @param source_voltages the (fixed) voltage for each source + * @param sinks the vertices whose voltages are tied to 0 + */ + public VoltageScorer(Hypergraph g, Transformer edge_weights, + Map source_voltages, Collection sinks) + { + super(g, edge_weights); + this.source_voltages = source_voltages; + this.sinks = sinks; + initialize(); + } + + /** + * Creates an instance with the specified graph, edge weights, source vertices + * (each of whose 'voltages' are tied to 1), and sinks. + * @param g the input graph + * @param edge_weights the edge weights, representing conductivity + * @param sources the vertices whose voltages are tied to 1 + * @param sinks the vertices whose voltages are tied to 0 + */ + public VoltageScorer(Hypergraph g, Transformer edge_weights, + Collection sources, Collection sinks) + { + super(g, edge_weights); + + Map unit_voltages = new HashMap(); + for(V v : sources) + unit_voltages.put(v, new Double(1.0)); + this.source_voltages = unit_voltages; + this.sinks = sinks; + initialize(); + } + + /** + * Creates an instance with the specified graph, source vertices + * (each of whose 'voltages' are tied to 1), and sinks. + * The outgoing edges for each vertex are assigned + * weights that sum to 1. + * @param g the input graph + * @param sources the vertices whose voltages are tied to 1 + * @param sinks the vertices whose voltages are tied to 0 + */ + public VoltageScorer(Hypergraph g, Collection sources, Collection sinks) + { + super(g); + + Map unit_voltages = new HashMap(); + for(V v : sources) + unit_voltages.put(v, new Double(1.0)); + this.source_voltages = unit_voltages; + this.sinks = sinks; + initialize(); + } + + /** + * Creates an instance with the specified graph, source voltages, + * and sinks. The outgoing edges for each vertex are assigned + * weights that sum to 1. + * @param g the input graph + * @param source_voltages the (fixed) voltage for each source + * @param sinks the vertices whose voltages are tied to 0 + */ + public VoltageScorer(Hypergraph g, Map source_voltages, + Collection sinks) + { + super(g); + this.source_voltages = source_voltages; + this.sinks = sinks; + this.edge_weights = new UniformDegreeWeight(g); + initialize(); + } + + /** + * Creates an instance with the specified graph, edge weights, source, and + * sink. The source vertex voltage is tied to 1. + * @param g the input graph + * @param edge_weights the edge weights, representing conductivity + * @param source the vertex whose voltage is tied to 1 + * @param sink the vertex whose voltage is tied to 0 + */ + public VoltageScorer(Hypergraph g, Transformer edge_weights, + V source, V sink) + { + this(g, edge_weights, Collections.singletonMap(source, 1.0), Collections.singletonList(sink)); + initialize(); + } + + /** + * Creates an instance with the specified graph, edge weights, source, and + * sink. The source vertex voltage is tied to 1. + * The outgoing edges for each vertex are assigned + * weights that sum to 1. + * @param g the input graph + * @param source the vertex whose voltage is tied to 1 + * @param sink the vertex whose voltage is tied to 0 + */ + public VoltageScorer(Hypergraph g, V source, V sink) + { + this(g, Collections.singletonMap(source, 1.0), Collections.singletonList(sink)); + initialize(); + } + + + /** + * Initializes the state of this instance. + */ + @Override + public void initialize() + { + super.initialize(); + + // sanity check + if (source_voltages.isEmpty() || sinks.isEmpty()) + throw new IllegalArgumentException("Both sources and sinks (grounds) must be defined"); + + if (source_voltages.size() + sinks.size() > graph.getVertexCount()) + throw new IllegalArgumentException("Source/sink sets overlap, or contain vertices not in graph"); + + for (Map.Entry entry : source_voltages.entrySet()) + { + V v = entry.getKey(); + if (sinks.contains(v)) + throw new IllegalArgumentException("Vertex " + v + " is incorrectly specified as both source and sink"); + double value = entry.getValue().doubleValue(); + if (value <= 0) + throw new IllegalArgumentException("Source vertex " + v + " has negative voltage"); + } + + // set up initial voltages + for (V v : graph.getVertices()) + { + if (source_voltages.containsKey(v)) + setOutputValue(v, source_voltages.get(v).doubleValue()); + else + setOutputValue(v, 0.0); + } + } + + /** + * @see edu.uci.ics.jung.algorithms.scoring.AbstractIterativeScorer#update(Object) + */ + @Override + public double update(V v) + { + // if it's a voltage source or sink, we're done + Number source_volts = source_voltages.get(v); + if (source_volts != null) + { + setOutputValue(v, source_volts.doubleValue()); + return 0.0; + } + if (sinks.contains(v)) + { + setOutputValue(v, 0.0); + return 0.0; + } + + Collection edges = graph.getInEdges(v); + double voltage_sum = 0; + double weight_sum = 0; + for (E e: edges) + { + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + { + double weight = getEdgeWeight(w,e).doubleValue() / incident_count; + voltage_sum += getCurrentValue(w).doubleValue() * weight; + weight_sum += weight; + } + } +// V w = graph.getOpposite(v, e); +// double weight = getEdgeWeight(w,e).doubleValue(); +// voltage_sum += getCurrentValue(w).doubleValue() * weight; +// weight_sum += weight; + } + + // if either is 0, new value is 0 + if (voltage_sum == 0 || weight_sum == 0) + { + setOutputValue(v, 0.0); + return getCurrentValue(v).doubleValue(); + } + + setOutputValue(v, voltage_sum / weight_sum); + return Math.abs(getCurrentValue(v).doubleValue() - voltage_sum / weight_sum); + } + +} + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/package.html new file mode 100644 index 0000000000..a1f8196ebf --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/package.html @@ -0,0 +1,43 @@ + + + + + + + +Mechanisms for assigning values (denoting significance, influence, centrality, etc.) +to graph elements based on topological properties. These include: + +
          +
        • BarycenterScorer: assigns a score to each vertex according to +the sum of the distances to all other vertices +
        • ClosenessCentrality: assigns a score to each vertex based on +the mean distance to each other vertex +
        • DegreeScorer: assigns a score to each vertex based on its degree +
        • EigenvectorCentrality: assigns vertex scores based on +long-term probabilities of random walks passing through the vertex at time t +
        • PageRank: like EigenvectorCentrality, but with +a constant probability of the +random walk restarting at a uniform-randomly chosen vertex +
        • PageRankWithPriors: like PageRank, but with a +constant probability of the random +walk restarting at a vertex drawn from an arbitrary distribution +
        • HITS: assigns hubs-and-authorities scores to vertices based on +complementary random walk processes +
        • HITSWithPriors: analogous to HITS +(see PageRankWithPriors) +
        • VoltageScorer: assigns scores to vertices based on simulated +current flow along edges +
        + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/DelegateToEdgeTransformer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/DelegateToEdgeTransformer.java new file mode 100644 index 0000000000..f836a9b428 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/DelegateToEdgeTransformer.java @@ -0,0 +1,48 @@ +/* + * Created on Jul 11, 2008 + * + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import org.apache.commons.collections15.Transformer; + +/** + * A Transformer that delegates its operation to a + * Transformer. Mainly useful for technical reasons inside + * AbstractIterativeScorer; in essence it allows the edge weight instance + * variable to be of type VEPair,W even if the edge weight + * Transformer only operates on edges. + */ +public class DelegateToEdgeTransformer implements + Transformer,Number> +{ + /** + * The transformer to which this instance delegates its function. + */ + protected Transformer delegate; + + /** + * Creates an instance with the specified delegate transformer. + * @param delegate the Transformer to which this instance will delegate + */ + public DelegateToEdgeTransformer(Transformer delegate) + { + this.delegate = delegate; + } + + /** + * @see Transformer#transform(Object) + */ + public Number transform(VEPair arg0) + { + return delegate.transform(arg0.getE()); + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/ScoringUtils.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/ScoringUtils.java new file mode 100644 index 0000000000..793944b295 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/ScoringUtils.java @@ -0,0 +1,72 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import java.util.Collection; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.HITS; + +/** + * Methods for assigning values (to be interpreted as prior probabilities) to vertices in the context + * of random-walk-based scoring algorithms. + */ +public class ScoringUtils +{ + /** + * Assigns a probability of 1/roots.size() to each of the elements of roots. + * @param the vertex type + * @param roots the vertices to be assigned nonzero prior probabilities + * @return + */ + public static Transformer getUniformRootPrior(Collection roots) + { + final Collection inner_roots = roots; + Transformer distribution = new Transformer() + { + public Double transform(V input) + { + if (inner_roots.contains(input)) + return new Double(1.0 / inner_roots.size()); + else + return 0.0; + } + }; + + return distribution; + } + + /** + * Returns a Transformer that hub and authority values of 1/roots.size() to each + * element of roots. + * @param the vertex type + * @param roots the vertices to be assigned nonzero scores + * @return a Transformer that assigns uniform prior hub/authority probabilities to each root + */ + public static Transformer getHITSUniformRootPrior(Collection roots) + { + final Collection inner_roots = roots; + Transformer distribution = + new Transformer() + { + public HITS.Scores transform(V input) + { + if (inner_roots.contains(input)) + return new HITS.Scores(1.0 / inner_roots.size(), 1.0 / inner_roots.size()); + else + return new HITS.Scores(0.0, 0.0); + } + }; + return distribution; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformDegreeWeight.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformDegreeWeight.java new file mode 100644 index 0000000000..f22bfcc891 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformDegreeWeight.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * Created on Jul 14, 2008 + * + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * An edge weight function that assigns weights as uniform + * transition probabilities. + * For undirected edges, returns 1/degree(v) (where 'v' is the + * vertex in the VEPair. + * For directed edges, returns 1/outdegree(source(e)) (where 'e' + * is the edge in the VEPair). + * Throws an IllegalArgumentException if the input + * edge is neither EdgeType.UNDIRECTED nor EdgeType.DIRECTED. + * + */ +public class UniformDegreeWeight implements + Transformer, Double> +{ + private Hypergraph graph; + + /** + * Creates an instance for the specified graph. + */ + public UniformDegreeWeight(Hypergraph graph) + { + this.graph = graph; + } + + /** + * @see org.apache.commons.collections15.Transformer#transform(java.lang.Object) + */ + public Double transform(VEPair ve_pair) + { + E e = ve_pair.getE(); + V v = ve_pair.getV(); + EdgeType edge_type = graph.getEdgeType(e); + if (edge_type == EdgeType.UNDIRECTED) + return 1.0 / graph.degree(v); + if (edge_type == EdgeType.DIRECTED) + return 1.0 / graph.outDegree(graph.getSource(e)); + throw new IllegalArgumentException("can't handle edge type: " + edge_type); + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformInOut.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformInOut.java new file mode 100644 index 0000000000..7853f002fd --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformInOut.java @@ -0,0 +1,57 @@ +/* + * Created on Jul 11, 2008 + * + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * Assigns weights to directed edges (the edge of the vertex/edge pair) depending on + * whether the vertex is the edge's source or its destination. + * If the vertex v is the edge's source, assigns 1/outdegree(v). + * Otherwise, assigns 1/indegree(w). + * Throws IllegalArgumentException if the edge is not directed. + */ +public class UniformInOut implements Transformer, Double> +{ + /** + * The graph for which the edge weights are defined. + */ + protected Graph graph; + + /** + * Creates an instance for the specified graph. + * @param graph the graph for which the edge weights will be defined + */ + public UniformInOut(Graph graph) + { + this.graph = graph; + } + + /** + * @see org.apache.commons.collections15.Transformer#transform(Object) + * @throws IllegalArgumentException + */ + public Double transform(VEPair ve_pair) + { + V v = ve_pair.getV(); + E e = ve_pair.getE(); + if (graph.getEdgeType(e) != EdgeType.DIRECTED) + throw new IllegalArgumentException("This transformer only" + + " operates on directed edges"); + return 1.0 / (graph.isSource(v, e) ? + graph.outDegree(v) : + graph.inDegree(v)); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VEPair.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VEPair.java new file mode 100644 index 0000000000..ad9029359b --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VEPair.java @@ -0,0 +1,56 @@ +/* + * Created on Jul 8, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +/** + * Convenience class for associating a vertex and an edge. Used, for example, + * in contexts in which it is necessary to know the origin for an edge traversal + * (that is, the direction in which an (undirected) edge is being traversed). + * + * @param the vertex type + * @param the edge type + */ +public class VEPair +{ + private V v; + private E e; + + /** + * Creates an instance with the specified vertex and edge + * @param v the vertex to add + * @param e the edge to add + */ + public VEPair(V v, E e) + { + if (v == null || e == null) + throw new IllegalArgumentException("elements must be non-null"); + + this.v = v; + this.e = e; + } + + /** + * Returns the vertex of this pair. + */ + public V getV() + { + return v; + } + + /** + * Returns the edge of this pair. + */ + public E getE() + { + return e; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VertexScoreTransformer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VertexScoreTransformer.java new file mode 100644 index 0000000000..851c08eef8 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VertexScoreTransformer.java @@ -0,0 +1,44 @@ +/* + * Created on Jul 18, 2008 + * + * Copyright (c) 2008, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.VertexScorer; + +/** + * A Transformer convenience wrapper around VertexScorer. + */ +public class VertexScoreTransformer implements Transformer +{ + /** + * The VertexScorer instance that provides the values returned by transform. + */ + protected VertexScorer vs; + + /** + * Creates an instance based on the specified VertexScorer. + */ + public VertexScoreTransformer(VertexScorer vs) + { + this.vs = vs; + } + + /** + * Returns the score for this vertex. + */ + public S transform(V v) + { + return vs.getVertexScore(v); + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/package.html new file mode 100644 index 0000000000..3bf18f3584 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/package.html @@ -0,0 +1,35 @@ + + + + + + + +Utility functions for assigning scores to graph elements. These include: +
          +
        • EdgeWeight: interface for classes that associate numeric values +with edges +
        • ScoringUtils: methods for calculating transition probabilities +for random-walk-based algorithms. +
        • UniformOut: an edge weight function that assigns weights as uniform +transition probabilities to all outgoing edges of a vertex. +
        • UniformIncident: an edge weight function that assigns +weights as uniform transition probabilities to all incident edges of a +vertex (useful for undirected graphs). +
        • VEPair: analogous to Pair but specifically +containing an associated vertex and edge. +
        • VertexEdgeWeight: a subtype of EdgeWeight that +assigns edge weights with respect to a specified 'source' vertex. +
        + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java new file mode 100644 index 0000000000..38d3b001d6 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java @@ -0,0 +1,169 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Labels each node in the graph according to the BFS distance from the start node(s). If nodes are unreachable, then + * they are assigned a distance of -1. + * All nodes traversed at step k are marked as predecessors of their successors traversed at step k+1. + *

        + * Running time is: O(m) + * @author Scott White + */ +public class BFSDistanceLabeler { + + private Map distanceDecorator = new HashMap(); + private List mCurrentList; + private Set mUnvisitedVertices; + private List mVerticesInOrderVisited; + private Map> mPredecessorMap; + + /** + * Creates a new BFS labeler for the specified graph and root set + * The distances are stored in the corresponding Vertex objects and are of type MutableInteger + */ + public BFSDistanceLabeler() { + mPredecessorMap = new HashMap>(); + } + + /** + * Returns the list of vertices visited in order of traversal + * @return the list of vertices + */ + public List getVerticesInOrderVisited() { + return mVerticesInOrderVisited; + } + + /** + * Returns the set of all vertices that were not visited + * @return the list of unvisited vertices + */ + public Set getUnvisitedVertices() { + return mUnvisitedVertices; + } + + /** + * Given a vertex, returns the shortest distance from any node in the root set to v + * @param v the vertex whose distance is to be retrieved + * @return the shortest distance from any node in the root set to v + */ + public int getDistance(Hypergraph g, V v) { + if (!g.getVertices().contains(v)) { + throw new IllegalArgumentException("Vertex is not contained in the graph."); + } + + return distanceDecorator.get(v).intValue(); + } + + /** + * Returns set of predecessors of the given vertex + * @param v the vertex whose predecessors are to be retrieved + * @return the set of predecessors + */ + public Set getPredecessors(V v) { + return mPredecessorMap.get(v); + } + + protected void initialize(Hypergraph g, Set rootSet) { + mVerticesInOrderVisited = new ArrayList(); + mUnvisitedVertices = new HashSet(); + for(V currentVertex : g.getVertices()) { + mUnvisitedVertices.add(currentVertex); + mPredecessorMap.put(currentVertex,new HashSet()); + } + + mCurrentList = new ArrayList(); + for(V v : rootSet) { + distanceDecorator.put(v, new Integer(0)); + mCurrentList.add(v); + mUnvisitedVertices.remove(v); + mVerticesInOrderVisited.add(v); + } + } + + private void addPredecessor(V predecessor,V sucessor) { + HashSet predecessors = mPredecessorMap.get(sucessor); + predecessors.add(predecessor); + } + + /** + * Computes the distances of all the node from the starting root nodes. If there is more than one root node + * the minimum distance from each root node is used as the designated distance to a given node. Also keeps track + * of the predecessors of each node traversed as well as the order of nodes traversed. + * @param graph the graph to label + * @param rootSet the set of starting vertices to traverse from + */ + public void labelDistances(Hypergraph graph, Set rootSet) { + + initialize(graph,rootSet); + + int distance = 1; + while (true) { + List newList = new ArrayList(); + for(V currentVertex : mCurrentList) { + if(graph.containsVertex(currentVertex)) { + for(V next : graph.getSuccessors(currentVertex)) { + visitNewVertex(currentVertex,next, distance, newList); + } + } + } + if (newList.size() == 0) break; + mCurrentList = newList; + distance++; + } + + for(V v : mUnvisitedVertices) { + distanceDecorator.put(v,new Integer(-1)); + } + } + + /** + * Computes the distances of all the node from the specified root node. Also keeps track + * of the predecessors of each node traversed as well as the order of nodes traversed. + * @param graph the graph to label + * @param root the single starting vertex to traverse from + */ + public void labelDistances(Hypergraph graph, V root) { + labelDistances(graph, Collections.singleton(root)); + } + + private void visitNewVertex(V predecessor, V neighbor, int distance, List newList) { + if (mUnvisitedVertices.contains(neighbor)) { + distanceDecorator.put(neighbor, new Integer(distance)); + newList.add(neighbor); + mVerticesInOrderVisited.add(neighbor); + mUnvisitedVertices.remove(neighbor); + } + int predecessorDistance = distanceDecorator.get(predecessor).intValue(); + int successorDistance = distanceDecorator.get(neighbor).intValue(); + if (predecessorDistance < successorDistance) { + addPredecessor(predecessor,neighbor); + } + } + + /** + * Returns a map from vertices to minimum distances from the original source(s). + * Must be called after {@code labelDistances} in order to contain valid data. + */ + public Map getDistanceDecorator() { + return distanceDecorator; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java new file mode 100644 index 0000000000..3e99e16096 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java @@ -0,0 +1,582 @@ +/* + * Created on Jul 9, 2005 + * + * Copyright (c) 2005, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.functors.ConstantTransformer; + +import edu.uci.ics.jung.algorithms.util.BasicMapEntry; +import edu.uci.ics.jung.algorithms.util.MapBinaryHeap; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + *

        Calculates distances in a specified graph, using + * Dijkstra's single-source-shortest-path algorithm. All edge weights + * in the graph must be nonnegative; if any edge with negative weight is + * found in the course of calculating distances, an + * IllegalArgumentException will be thrown. + * (Note: this exception will only be thrown when such an edge would be + * used to update a given tentative distance; + * the algorithm does not check for negative-weight edges "up front".) + * + *

        Distances and partial results are optionally cached (by this instance) + * for later reference. Thus, if the 10 closest vertices to a specified source + * vertex are known, calculating the 20 closest vertices does not require + * starting Dijkstra's algorithm over from scratch.

        + * + *

        Distances are stored as double-precision values. + * If a vertex is not reachable from the specified source vertex, no + * distance is stored. This is new behavior with version 1.4; + * the previous behavior was to store a value of + * Double.POSITIVE_INFINITY. This change gives the algorithm + * an approximate complexity of O(kD log k), where k is either the number of + * requested targets or the number of reachable vertices (whichever is smaller), + * and D is the average degree of a vertex.

        + * + *

        The elements in the maps returned by getDistanceMap + * are ordered (that is, returned + * by the iterator) by nondecreasing distance from source.

        + * + *

        Users are cautioned that distances calculated should be assumed to + * be invalidated by changes to the graph, and should invoke reset() + * when appropriate so that the distances can be recalculated.

        + * + * @author Joshua O'Madadhain + * @author Tom Nelson converted to jung2 + */ +public class DijkstraDistance implements Distance +{ + protected Hypergraph g; + protected Transformer nev; + protected Map sourceMap; // a map of source vertices to an instance of SourceData + protected boolean cached; + protected double max_distance; + protected int max_targets; + + /** + *

        Creates an instance of DijkstraShortestPath for + * the specified graph and the specified method of extracting weights + * from edges, which caches results locally if and only if + * cached is true. + * + * @param g the graph on which distances will be calculated + * @param nev the class responsible for returning weights for edges + * @param cached specifies whether the results are to be cached + */ + public DijkstraDistance(Hypergraph g, Transformer nev, boolean cached) { + this.g = g; + this.nev = nev; + this.sourceMap = new HashMap(); + this.cached = cached; + this.max_distance = Double.POSITIVE_INFINITY; + this.max_targets = Integer.MAX_VALUE; + } + + /** + *

        Creates an instance of DijkstraShortestPath for + * the specified graph and the specified method of extracting weights + * from edges, which caches results locally. + * + * @param g the graph on which distances will be calculated + * @param nev the class responsible for returning weights for edges + */ + public DijkstraDistance(Hypergraph g, Transformer nev) { + this(g, nev, true); + } + + /** + *

        Creates an instance of DijkstraShortestPath for + * the specified unweighted graph (that is, all weights 1) which + * caches results locally. + * + * @param g the graph on which distances will be calculated + */ + @SuppressWarnings("unchecked") + public DijkstraDistance(Hypergraph g) { + this(g, new ConstantTransformer(1), true); + } + + /** + *

        Creates an instance of DijkstraShortestPath for + * the specified unweighted graph (that is, all weights 1) which + * caches results locally. + * + * @param g the graph on which distances will be calculated + * @param cached specifies whether the results are to be cached + */ + @SuppressWarnings("unchecked") + public DijkstraDistance(Hypergraph g, boolean cached) { + this(g, new ConstantTransformer(1), cached); + } + + /** + * Implements Dijkstra's single-source shortest-path algorithm for + * weighted graphs. Uses a MapBinaryHeap as the priority queue, + * which gives this algorithm a time complexity of O(m lg n) (m = # of edges, n = + * # of vertices). + * This algorithm will terminate when any of the following have occurred (in order + * of priority): + *

          + *
        • the distance to the specified target (if any) has been found + *
        • no more vertices are reachable + *
        • the specified # of distances have been found, or the maximum distance + * desired has been exceeded + *
        • all distances have been found + *
        + * + * @param source the vertex from which distances are to be measured + * @param numDests the number of distances to measure + * @param targets the set of vertices to which distances are to be measured + * @param regular boolean is true if we want regular SP dijkstra. False for MT. + */ + private LinkedHashMap singleSourceShortestPath(V source, Collection targets, int numDests, boolean regular) + { + SourceData sd = getSourceData(source); + + Set to_get = new HashSet(); + if (targets != null) { + to_get.addAll(targets); + Set existing_dists = sd.distances.keySet(); + for(V o : targets) { + if (existing_dists.contains(o)) + to_get.remove(o); + } + } + + // if we've exceeded the max distance or max # of distances we're willing to calculate, or + // if we already have all the distances we need, + // terminate + if (sd.reached_max || + (targets != null && to_get.isEmpty()) || + (sd.distances.size() >= numDests)) + { + return sd.distances; + } + + while (!sd.unknownVertices.isEmpty() && (sd.distances.size() < numDests || !to_get.isEmpty())) + { + Map.Entry p = sd.getNextVertex(); + V v = p.getKey(); + double v_dist = p.getValue().doubleValue(); + to_get.remove(v); + if (v_dist > this.max_distance) + { + // we're done; put this vertex back in so that we're not including + // a distance beyond what we specified + sd.restoreVertex(v, v_dist); + sd.reached_max = true; + break; + } + sd.dist_reached = v_dist; + + if (sd.distances.size() >= this.max_targets) + { + sd.reached_max = true; + break; + } + + for (E e : getEdgesToCheck(v) ) + { + for (V w : g.getIncidentVertices(e)) + { + if (!sd.distances.containsKey(w)) + { + double edge_weight = nev.transform(e).doubleValue(); + if (edge_weight < 0) + throw new IllegalArgumentException("Edges weights must be non-negative"); + double new_dist; + if (regular == true) { + new_dist = v_dist + edge_weight; + } else { + if (v_dist <= edge_weight) { + new_dist = edge_weight; + } else { + new_dist = v_dist; + } + } + if (!sd.estimatedDistances.containsKey(w)) + { + sd.createRecord(w, e, new_dist); + } + else + { + double w_dist = ((Double)sd.estimatedDistances.get(w)).doubleValue(); + if (new_dist < w_dist) // update tentative distance & path for w + sd.update(w, e, new_dist); + } + } + } + } + } + return sd.distances; + } + + /** + * Implements Dijkstra's single-source shortest-path algorithm for + * weighted graphs. Uses a MapBinaryHeap as the priority queue, + * which gives this algorithm a time complexity of O(m lg n) (m = # of edges, n = + * # of vertices). + * This algorithm will terminate when any of the following have occurred (in order + * of priority): + *
          + *
        • the distance to the specified target (if any) has been found + *
        • no more vertices are reachable + *
        • the specified # of distances have been found, or the maximum distance + * desired has been exceeded + *
        • all distances have been found + *
        + * + * @param source the vertex from which distances are to be measured + * @param numDests the number of distances to measure + * @param targets the set of vertices to which distances are to be measured + */ + protected LinkedHashMap singleSourceShortestPath(V source, Collection targets, int numDests) + { + return singleSourceShortestPath(source, targets, numDests, true); + } + + /** + * Implements Dijkstra's single-source shortest-path algorithm for + * weighted graphs. Uses a MapBinaryHeap as the priority queue, + * which gives this algorithm a time complexity of O(m lg n) (m = # of edges, n = + * # of vertices). + * This algorithm will terminate when any of the following have occurred (in order + * of priority): + *
          + *
        • the distance to the specified target (if any) has been found + *
        • no more vertices are reachable + *
        • the specified # of distances have been found, or the maximum distance + * desired has been exceeded + *
        • all distances have been found + *
        + * + * @param source the vertex from which distances are to be measured + * @param numDests the number of distances to measure + * @param targets the set of vertices to which distances are to be measured + */ + protected LinkedHashMap singleSourceMaxThroughputPath(V source, Collection targets, int numDests) + { + return singleSourceShortestPath(source, targets, numDests, false); + } + + protected SourceData getSourceData(V source) + { + SourceData sd = sourceMap.get(source); + if (sd == null) + sd = new SourceData(source); + return sd; + } + + /** + * Returns the set of edges incident to v that should be tested. + * By default, this is the set of outgoing edges for instances of Graph, + * the set of incident edges for instances of Hypergraph, + * and is otherwise undefined. + */ + protected Collection getEdgesToCheck(V v) + { + if (g instanceof Graph) + return ((Graph)g).getOutEdges(v); + else + return g.getIncidentEdges(v); + + } + + + /** + * Returns the length of a shortest path from the source to the target vertex, + * or null if the target is not reachable from the source. + * If either vertex is not in the graph for which this instance + * was created, throws IllegalArgumentException. + * + * @see #getDistanceMap(Object) + * @see #getDistanceMap(Object,int) + */ + public Number getDistance(V source, V target) + { + if (g.containsVertex(target) == false) + throw new IllegalArgumentException("Specified target vertex " + + target + " is not part of graph " + g); + if (g.containsVertex(source) == false) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + Set targets = new HashSet(); + targets.add(target); + Map distanceMap = getDistanceMap(source, targets); + return distanceMap.get(target); + } + + + /** + * Returns a {@code Map} from each element {@code t} of {@code targets} to the + * shortest-path distance from {@code source} to {@code t}. + */ + public Map getDistanceMap(V source, Collection targets) + { + if (g.containsVertex(source) == false) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + if (targets.size() > max_targets) + throw new IllegalArgumentException("size of target set exceeds maximum " + + "number of targets allowed: " + this.max_targets); + + Map distanceMap = + singleSourceShortestPath(source, targets, + Math.min(g.getVertexCount(), max_targets)); + if (!cached) + reset(source); + + return distanceMap; + } + + /** + *

        Returns a LinkedHashMap which maps each vertex + * in the graph (including the source vertex) + * to its distance from the source vertex. + * The map's iterator will return the elements in order of + * increasing distance from source.

        + * + *

        The size of the map returned will be the number of + * vertices reachable from source.

        + * + * @see #getDistanceMap(Object,int) + * @see #getDistance(Object,Object) + * @param source the vertex from which distances are measured + */ + public Map getDistanceMap(V source) + { + return getDistanceMap(source, Math.min(g.getVertexCount(), max_targets)); + } + + + + /** + *

        Returns a LinkedHashMap which maps each of the closest + * numDist vertices to the source vertex + * in the graph (including the source vertex) + * to its distance from the source vertex. Throws + * an IllegalArgumentException if source + * is not in this instance's graph, or if numDests is + * either less than 1 or greater than the number of vertices in the + * graph.

        + * + *

        The size of the map returned will be the smaller of + * numDests and the number of vertices reachable from + * source. + * + * @see #getDistanceMap(Object) + * @see #getDistance(Object,Object) + * @param source the vertex from which distances are measured + * @param numDests the number of vertices for which to measure distances + */ + public LinkedHashMap getDistanceMap(V source, int numDests) + { + + if(g.getVertices().contains(source) == false) { + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + } + if (numDests < 1 || numDests > g.getVertexCount()) + throw new IllegalArgumentException("numDests must be >= 1 " + + "and <= g.numVertices()"); + + if (numDests > max_targets) + throw new IllegalArgumentException("numDests must be <= the maximum " + + "number of targets allowed: " + this.max_targets); + + LinkedHashMap distanceMap = + singleSourceShortestPath(source, null, numDests); + + if (!cached) + reset(source); + + return distanceMap; + } + + /** + * Allows the user to specify the maximum distance that this instance will calculate. + * Any vertices past this distance will effectively be unreachable from the source, in + * the sense that the algorithm will not calculate the distance to any vertices which + * are farther away than this distance. A negative value for max_dist + * will ensure that no further distances are calculated. + * + *

        This can be useful for limiting the amount of time and space used by this algorithm + * if the graph is very large.

        + * + *

        Note: if this instance has already calculated distances greater than max_dist, + * and the results are cached, those results will still be valid and available; this limit + * applies only to subsequent distance calculations.

        + * @see #setMaxTargets(int) + */ + public void setMaxDistance(double max_dist) + { + this.max_distance = max_dist; + for (V v : sourceMap.keySet()) + { + SourceData sd = sourceMap.get(v); + sd.reached_max = (this.max_distance <= sd.dist_reached) || (sd.distances.size() >= max_targets); + } + } + + /** + * Allows the user to specify the maximum number of target vertices per source vertex + * for which this instance will calculate distances. Once this threshold is reached, + * any further vertices will effectively be unreachable from the source, in + * the sense that the algorithm will not calculate the distance to any more vertices. + * A negative value for max_targets will ensure that no further distances are calculated. + * + *

        This can be useful for limiting the amount of time and space used by this algorithm + * if the graph is very large.

        + * + *

        Note: if this instance has already calculated distances to a greater number of + * targets than max_targets, and the results are cached, those results + * will still be valid and available; this limit applies only to subsequent distance + * calculations.

        + * @see #setMaxDistance(double) + */ + public void setMaxTargets(int max_targets) + { + this.max_targets = max_targets; + for (V v : sourceMap.keySet()) + { + SourceData sd = sourceMap.get(v); + sd.reached_max = (this.max_distance <= sd.dist_reached) || (sd.distances.size() >= max_targets); + } + } + + /** + * Clears all stored distances for this instance. + * Should be called whenever the graph is modified (edge weights + * changed or edges added/removed). If the user knows that + * some currently calculated distances are unaffected by a + * change, reset(V) may be appropriate instead. + * + * @see #reset(Object) + */ + public void reset() + { + sourceMap = new HashMap(); + } + + /** + * Specifies whether or not this instance of DijkstraShortestPath + * should cache its results (final and partial) for future reference. + * + * @param enable true if the results are to be cached, and + * false otherwise + */ + public void enableCaching(boolean enable) + { + this.cached = enable; + } + + /** + * Clears all stored distances for the specified source vertex + * source. Should be called whenever the stored distances + * from this vertex are invalidated by changes to the graph. + * + * @see #reset() + */ + public void reset(V source) + { + sourceMap.put(source, null); + } + + /** + * Compares according to distances, so that the BinaryHeap knows how to + * order the tree. + */ + protected static class VertexComparator implements Comparator + { + private Map distances; + + protected VertexComparator(Map distances) + { + this.distances = distances; + } + + public int compare(V o1, V o2) + { + return ((Double) distances.get(o1)).compareTo((Double) distances.get(o2)); + } + } + + /** + * For a given source vertex, holds the estimated and final distances, + * tentative and final assignments of incoming edges on the shortest path from + * the source vertex, and a priority queue (ordered by estimated distance) + * of the vertices for which distances are unknown. + * + * @author Joshua O'Madadhain + */ + protected class SourceData + { + protected LinkedHashMap distances; + protected Map estimatedDistances; + protected MapBinaryHeap unknownVertices; + protected boolean reached_max = false; + protected double dist_reached = 0; + + protected SourceData(V source) + { + distances = new LinkedHashMap(); + estimatedDistances = new HashMap(); + unknownVertices = new MapBinaryHeap(new VertexComparator(estimatedDistances)); + + sourceMap.put(source, this); + + // initialize priority queue + estimatedDistances.put(source, new Double(0)); // distance from source to itself is 0 + unknownVertices.add(source); + reached_max = false; + dist_reached = 0; + } + + protected Map.Entry getNextVertex() + { + V v = unknownVertices.remove(); + Double dist = (Double)estimatedDistances.remove(v); + distances.put(v, dist); + return new BasicMapEntry(v, dist); + } + + protected void update(V dest, E tentative_edge, double new_dist) + { + estimatedDistances.put(dest, new_dist); + unknownVertices.update(dest); + } + + protected void createRecord(V w, E e, double new_dist) + { + estimatedDistances.put(w, new_dist); + unknownVertices.add(w); + } + + protected void restoreVertex(V v, double dist) + { + estimatedDistances.put(v, dist); + unknownVertices.add(v); + distances.remove(v); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraShortestPath.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraShortestPath.java new file mode 100644 index 0000000000..05c008d11f --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraShortestPath.java @@ -0,0 +1,314 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.graph.Graph; + +/** + *

        Calculates distances and shortest paths using Dijkstra's + * single-source-shortest-path algorithm. This is a lightweight + * extension of DijkstraDistance that also stores + * path information, so that the shortest paths can be reconstructed.

        + * + *

        The elements in the maps returned by + * getIncomingEdgeMap are ordered (that is, returned + * by the iterator) by nondecreasing distance from source.

        + * + * @author Joshua O'Madadhain + * @author Tom Nelson converted to jung2 + * @see DijkstraDistance + */ +public class DijkstraShortestPath extends DijkstraDistance implements ShortestPath +{ + /** + *

        Creates an instance of DijkstraShortestPath for + * the specified graph and the specified method of extracting weights + * from edges, which caches results locally if and only if + * cached is true. + * + * @param g the graph on which distances will be calculated + * @param nev the class responsible for returning weights for edges + * @param cached specifies whether the results are to be cached + */ + public DijkstraShortestPath(Graph g, Transformer nev, boolean cached) + { + super(g, nev, cached); + } + + /** + *

        Creates an instance of DijkstraShortestPath for + * the specified graph and the specified method of extracting weights + * from edges, which caches results locally. + * + * @param g the graph on which distances will be calculated + * @param nev the class responsible for returning weights for edges + */ + public DijkstraShortestPath(Graph g, Transformer nev) + { + super(g, nev); + } + + /** + *

        Creates an instance of DijkstraShortestPath for + * the specified unweighted graph (that is, all weights 1) which + * caches results locally. + * + * @param g the graph on which distances will be calculated + */ + public DijkstraShortestPath(Graph g) + { + super(g); + } + + /** + *

        Creates an instance of DijkstraShortestPath for + * the specified unweighted graph (that is, all weights 1) which + * caches results locally. + * + * @param g the graph on which distances will be calculated + * @param cached specifies whether the results are to be cached + */ + public DijkstraShortestPath(Graph g, boolean cached) + { + super(g, cached); + } + + @Override + protected SourceData getSourceData(V source) + { + SourceData sd = sourceMap.get(source); + if (sd == null) + sd = new SourcePathData(source); + return sd; + } + + /** + *

        Returns the last edge on a shortest path from source + * to target, or null if target is not + * reachable from source.

        + * + *

        If either vertex is not in the graph for which this instance + * was created, throws IllegalArgumentException.

        + */ + public E getIncomingEdge(V source, V target) + { + if (!g.containsVertex(source)) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + if (!g.containsVertex(target)) + throw new IllegalArgumentException("Specified target vertex " + + target + " is not part of graph " + g); + + Set targets = new HashSet(); + targets.add(target); + singleSourceShortestPath(source, targets, g.getVertexCount()); + Map incomingEdgeMap = + ((SourcePathData)sourceMap.get(source)).incomingEdges; + E incomingEdge = incomingEdgeMap.get(target); + + if (!cached) + reset(source); + + return incomingEdge; + } + + /** + *

        Returns a LinkedHashMap which maps each vertex + * in the graph (including the source vertex) + * to the last edge on the shortest path from the + * source vertex. + * The map's iterator will return the elements in order of + * increasing distance from source.

        + * + * @see DijkstraDistance#getDistanceMap(Object,int) + * @see DijkstraDistance#getDistance(Object,Object) + * @param source the vertex from which distances are measured + */ + public Map getIncomingEdgeMap(V source) + { + return getIncomingEdgeMap(source, g.getVertexCount()); + } + + /** + * Returns a List of the edges on the shortest path from + * source to target, in order of their + * occurrence on this path. + * If either vertex is not in the graph for which this instance + * was created, throws IllegalArgumentException. + */ + private List getPath(V source, V target, boolean spath) + { + if(!g.containsVertex(source)) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + if(!g.containsVertex(target)) + throw new IllegalArgumentException("Specified target vertex " + + target + " is not part of graph " + g); + + LinkedList path = new LinkedList(); + + // collect path data; must use internal method rather than + // calling getIncomingEdge() because getIncomingEdge() may + // wipe out results if results are not cached + Set targets = new HashSet(); + targets.add(target); + if (spath == true) { + singleSourceShortestPath(source, targets, g.getVertexCount()); + } else { + singleSourceMaxThroughputPath(source, targets, g.getVertexCount()); + } + Map incomingEdges = + ((SourcePathData)sourceMap.get(source)).incomingEdges; + + if (incomingEdges.isEmpty() || incomingEdges.get(target) == null) + return path; + V current = target; + while (!current.equals(source)) + { + E incoming = incomingEdges.get(current); + path.addFirst(incoming); + current = ((Graph)g).getOpposite(current, incoming); + } + return path; + } + + /** + * Returns a List of the edges on the shortest path from + * source to target, in order of their + * occurrence on this path. + * If either vertex is not in the graph for which this instance + * was created, throws IllegalArgumentException. + */ + public List getPath(V source, V target) + { + + return getPath(source,target, true); + } + + /** + * Returns a List of the edges on the Max Througput Shortest + * path from source to target, in order of their + * their occurrence on this path. + * Important - Transformer fn should return the appropriate edge weight + * for this API to return the Path Correctly. + * If either vertex is not in the graph for which this instance + * was created, throws IllegalArgumentException. + */ + public List getMaxThroughputPath(V source, V target) + { + + return getPath(source,target, false); + } + + + /** + *

        Returns a LinkedHashMap which maps each of the closest + * numDist vertices to the source vertex + * in the graph (including the source vertex) + * to the incoming edge along the path from that vertex. Throws + * an IllegalArgumentException if source + * is not in this instance's graph, or if numDests is + * either less than 1 or greater than the number of vertices in the + * graph. + * + * @see #getIncomingEdgeMap(Object) + * @see #getPath(Object,Object) + * @param source the vertex from which distances are measured + * @param numDests the number of vertices for which to measure distances + */ + public LinkedHashMap getIncomingEdgeMap(V source, int numDests) + { + if (g.getVertices().contains(source) == false) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + if (numDests < 1 || numDests > g.getVertexCount()) + throw new IllegalArgumentException("numDests must be >= 1 " + + "and <= g.numVertices()"); + + singleSourceShortestPath(source, null, numDests); + + LinkedHashMap incomingEdgeMap = + ((SourcePathData)sourceMap.get(source)).incomingEdges; + + if (!cached) + reset(source); + + return incomingEdgeMap; + } + + + /** + * For a given source vertex, holds the estimated and final distances, + * tentative and final assignments of incoming edges on the shortest path from + * the source vertex, and a priority queue (ordered by estimaed distance) + * of the vertices for which distances are unknown. + * + * @author Joshua O'Madadhain + */ + protected class SourcePathData extends SourceData + { + protected Map tentativeIncomingEdges; + protected LinkedHashMap incomingEdges; + + protected SourcePathData(V source) + { + super(source); + incomingEdges = new LinkedHashMap(); + tentativeIncomingEdges = new HashMap(); + } + + @Override + public void update(V dest, E tentative_edge, double new_dist) + { + super.update(dest, tentative_edge, new_dist); + tentativeIncomingEdges.put(dest, tentative_edge); + } + + @Override + public Map.Entry getNextVertex() + { + Map.Entry p = super.getNextVertex(); + V v = p.getKey(); + E incoming = tentativeIncomingEdges.remove(v); + incomingEdges.put(v, incoming); + return p; + } + + @Override + public void restoreVertex(V v, double dist) + { + super.restoreVertex(v, dist); + E incoming = incomingEdges.get(v); + tentativeIncomingEdges.put(v, incoming); + } + + @Override + public void createRecord(V w, E e, double new_dist) + { + super.createRecord(w, e, new_dist); + tentativeIncomingEdges.put(w, e); + } + + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/Distance.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/Distance.java new file mode 100644 index 0000000000..85820d14b8 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/Distance.java @@ -0,0 +1,41 @@ +/* + * Created on Apr 2, 2004 + * + * Copyright (c) 2004, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Map; + + +/** + * An interface for classes which calculate the distance between + * one vertex and another. + * + * @author Joshua O'Madadhain + */ +public interface Distance +{ + /** + * Returns the distance from the source vertex + * to the target vertex. If target + * is not reachable from source, returns null. + */ + Number getDistance(V source, V target); + + /** + *

        Returns a Map which maps each vertex + * in the graph (including the source vertex) + * to its distance (represented as a Number) + * from source. If any vertex + * is not reachable from source, no + * distance is stored for that vertex. + */ + Map getDistanceMap(V source); +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DistanceStatistics.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DistanceStatistics.java new file mode 100644 index 0000000000..f0f20a3241 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DistanceStatistics.java @@ -0,0 +1,136 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; +import java.util.Collection; + +import org.apache.commons.collections15.Transformer; + +import edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality; +import edu.uci.ics.jung.algorithms.scoring.util.VertexScoreTransformer; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Statistics relating to vertex-vertex distances in a graph. + * + *

        Formerly known as GraphStatistics in JUNG 1.x.

        + * + * @author Scott White + * @author Joshua O'Madadhain + */ +public class DistanceStatistics +{ + /** + * For each vertex v in graph, + * calculates the average shortest path length from v + * to all other vertices in graph using the metric + * specified by d, and returns the results in a + * Map from vertices to Double values. + * If there exists an ordered pair <u,v> + * for which d.getDistance(u,v) returns null, + * then the average distance value for u will be stored + * as Double.POSITIVE_INFINITY). + * + *

        Does not include self-distances (path lengths from v + * to v). + * + *

        To calculate the average distances, ignoring edge weights if any: + *

        +     * Map distances = DistanceStatistics.averageDistances(g, new UnweightedShortestPath(g));
        +     * 
        + * To calculate the average distances respecting edge weights: + *
        +     * DijkstraShortestPath dsp = new DijkstraShortestPath(g, nev);
        +     * Map distances = DistanceStatistics.averageDistances(g, dsp);
        +     * 
        + * where nev is an instance of Transformer that + * is used to fetch the weight for each edge. + * + * @see edu.uci.ics.jung.algorithms.shortestpath.UnweightedShortestPath + * @see edu.uci.ics.jung.algorithms.shortestpath.DijkstraDistance + */ + public static Transformer averageDistances(Hypergraph graph, Distance d) + { + final ClosenessCentrality cc = new ClosenessCentrality(graph, d); + return new VertexScoreTransformer(cc); + } + + /** + * For each vertex v in g, + * calculates the average shortest path length from v + * to all other vertices in g, ignoring edge weights. + * @see #diameter(Hypergraph) + * @see edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality + */ + public static Transformer averageDistances(Hypergraph g) + { + final ClosenessCentrality cc = new ClosenessCentrality(g, + new UnweightedShortestPath(g)); + return new VertexScoreTransformer(cc); + } + + /** + * Returns the diameter of g using the metric + * specified by d. The diameter is defined to be + * the maximum, over all pairs of vertices u,v, + * of the length of the shortest path from u to + * v. If the graph is disconnected (that is, not + * all pairs of vertices are reachable from one another), the + * value returned will depend on use_max: + * if use_max == true, the value returned + * will be the the maximum shortest path length over all pairs of connected + * vertices; otherwise it will be Double.POSITIVE_INFINITY. + */ + public static double diameter(Hypergraph g, Distance d, boolean use_max) + { + double diameter = 0; + Collection vertices = g.getVertices(); + for(V v : vertices) { + for(V w : vertices) { + + if (v.equals(w) == false) // don't include self-distances + { + Number dist = d.getDistance(v, w); + if (dist == null) + { + if (!use_max) + return Double.POSITIVE_INFINITY; + } + else + diameter = Math.max(diameter, dist.doubleValue()); + } + } + } + return diameter; + } + + /** + * Returns the diameter of g using the metric + * specified by d. The diameter is defined to be + * the maximum, over all pairs of vertices u,v, + * of the length of the shortest path from u to + * v, or Double.POSITIVE_INFINITY + * if any of these distances do not exist. + * @see #diameter(Hypergraph, Distance, boolean) + */ + public static double diameter(Hypergraph g, Distance d) + { + return diameter(g, d, false); + } + + /** + * Returns the diameter of g, ignoring edge weights. + * @see #diameter(Hypergraph, Distance, boolean) + */ + public static double diameter(Hypergraph g) + { + return diameter(g, new UnweightedShortestPath(g)); + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest.java new file mode 100644 index 0000000000..18cb0fe026 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest.java @@ -0,0 +1,165 @@ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.functors.ConstantTransformer; +import org.apache.commons.collections15.map.LazyMap; + +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * For the input Graph, creates a MinimumSpanningTree + * using a variation of Prim's algorithm. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param + * @param + */ +public class MinimumSpanningForest { + + protected Graph graph; + protected Forest forest; + protected Map weights; + + /** + * Creates a Forest from the supplied Graph and supplied Factory, which + * is used to create a new, empty Forest. If non-null, the supplied root + * will be used as the root of the tree/forest. If the supplied root is + * null, or not present in the Graph, then an arbitrary Graph vertex + * will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created. + * @param graph the input graph + * @param factory the factory to use to create the new forest + * @param root the vertex of the graph to be used as the root of the forest + * @param weights edge weights + */ + public MinimumSpanningForest(Graph graph, Factory> factory, + V root, Map weights) { + this(graph, factory.create(), root, weights); + } + + /** + * Creates a minimum spanning forest from the supplied graph, populating the + * supplied Forest, which must be empty. + * If the supplied root is null, or not present in the Graph, + * then an arbitrary Graph vertex will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created + * @param graph the Graph to find MST in + * @param forest the Forest to populate. Must be empty + * @param root first Tree root, may be null + * @param weights edge weights, may be null + */ + public MinimumSpanningForest(Graph graph, Forest forest, + V root, Map weights) { + + if(forest.getVertexCount() != 0) { + throw new IllegalArgumentException("Supplied Forest must be empty"); + } + this.graph = graph; + this.forest = forest; + if(weights != null) { + this.weights = weights; + } + Set unfinishedEdges = new HashSet(graph.getEdges()); + if(graph.getVertices().contains(root)) { + this.forest.addVertex(root); + } + updateForest(forest.getVertices(), unfinishedEdges); + } + + /** + * Creates a minimum spanning forest from the supplied graph, populating the + * supplied Forest, which must be empty. + * If the supplied root is null, or not present in the Graph, + * then an arbitrary Graph vertex will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created + * @param graph the Graph to find MST in + * @param forest the Forest to populate. Must be empty + * @param root first Tree root, may be null + */ + @SuppressWarnings("unchecked") + public MinimumSpanningForest(Graph graph, Forest forest, + V root) { + + if(forest.getVertexCount() != 0) { + throw new IllegalArgumentException("Supplied Forest must be empty"); + } + this.graph = graph; + this.forest = forest; + this.weights = LazyMap.decorate(new HashMap(), + new ConstantTransformer(1.0)); + Set unfinishedEdges = new HashSet(graph.getEdges()); + if(graph.getVertices().contains(root)) { + this.forest.addVertex(root); + } + updateForest(forest.getVertices(), unfinishedEdges); + } + + /** + * Returns the generated forest. + */ + public Forest getForest() { + return forest; + } + + protected void updateForest(Collection tv, Collection unfinishedEdges) { + double minCost = Double.MAX_VALUE; + E nextEdge = null; + V nextVertex = null; + V currentVertex = null; + for(E e : unfinishedEdges) { + + if(forest.getEdges().contains(e)) continue; + // find the lowest cost edge, get its opposite endpoint, + // and then update forest from its Successors + Pair endpoints = graph.getEndpoints(e); + V first = endpoints.getFirst(); + V second = endpoints.getSecond(); + if(tv.contains(first) == true && tv.contains(second) == false) { + if(weights.get(e) < minCost) { + minCost = weights.get(e); + nextEdge = e; + currentVertex = first; + nextVertex = second; + } + } + if(graph.getEdgeType(e) == EdgeType.UNDIRECTED && + tv.contains(second) == true && tv.contains(first) == false) { + if(weights.get(e) < minCost) { + minCost = weights.get(e); + nextEdge = e; + currentVertex = second; + nextVertex = first; + } + } + } + + if(nextVertex != null && nextEdge != null) { + unfinishedEdges.remove(nextEdge); + forest.addEdge(nextEdge, currentVertex, nextVertex); + updateForest(forest.getVertices(), unfinishedEdges); + } + Collection leftovers = new HashSet(graph.getVertices()); + leftovers.removeAll(forest.getVertices()); + if(leftovers.size() > 0) { + V anotherRoot = leftovers.iterator().next(); + forest.addVertex(anotherRoot); + updateForest(forest.getVertices(), unfinishedEdges); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java new file mode 100644 index 0000000000..13e800c7d5 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java @@ -0,0 +1,104 @@ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Collection; +import java.util.Set; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.functors.ConstantTransformer; + +import edu.uci.ics.jung.algorithms.cluster.WeakComponentClusterer; +import edu.uci.ics.jung.algorithms.filters.FilterUtils; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.graph.util.TreeUtils; + +/** + * For the input Graph, creates a MinimumSpanningTree + * using a variation of Prim's algorithm. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param + * @param + */ +@SuppressWarnings("unchecked") +public class MinimumSpanningForest2 { + + protected Graph graph; + protected Forest forest; + protected Transformer weights = + (Transformer)new ConstantTransformer(1.0); + + /** + * create a Forest from the supplied Graph and supplied Factory, which + * is used to create a new, empty Forest. If non-null, the supplied root + * will be used as the root of the tree/forest. If the supplied root is + * null, or not present in the Graph, then an arbitary Graph vertex + * will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created + * @param graph + * @param factory + * @param weights + */ + public MinimumSpanningForest2(Graph graph, + Factory> factory, + Factory> treeFactory, + Transformer weights) { + this(graph, factory.create(), + treeFactory, + weights); + } + + /** + * create a forest from the supplied graph, populating the + * supplied Forest, which must be empty. + * If the supplied root is null, or not present in the Graph, + * then an arbitary Graph vertex will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created + * @param graph the Graph to find MST in + * @param forest the Forest to populate. Must be empty + * @param weights edge weights, may be null + */ + public MinimumSpanningForest2(Graph graph, + Forest forest, + Factory> treeFactory, + Transformer weights) { + + if(forest.getVertexCount() != 0) { + throw new IllegalArgumentException("Supplied Forest must be empty"); + } + this.graph = graph; + this.forest = forest; + if(weights != null) { + this.weights = weights; + } + + WeakComponentClusterer wcc = + new WeakComponentClusterer(); + Set> component_vertices = wcc.transform(graph); + Collection> components = + FilterUtils.createAllInducedSubgraphs(component_vertices, graph); + + for(Graph component : components) { + PrimMinimumSpanningTree mst = + new PrimMinimumSpanningTree(treeFactory, this.weights); + Graph subTree = mst.transform(component); + if(subTree instanceof Tree) { + TreeUtils.addSubTree(forest, (Tree)subTree, null, null); + } + } + } + + /** + * Returns the generated forest. + */ + public Forest getForest() { + return forest; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/PrimMinimumSpanningTree.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/PrimMinimumSpanningTree.java new file mode 100644 index 0000000000..b029dda747 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/PrimMinimumSpanningTree.java @@ -0,0 +1,116 @@ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.functors.ConstantTransformer; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * For the input Graph, creates a MinimumSpanningTree + * using a variation of Prim's algorithm. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the vertex type + * @param the edge type + */ +@SuppressWarnings("unchecked") +public class PrimMinimumSpanningTree implements Transformer,Graph> { + + protected Factory> treeFactory; + protected Transformer weights; + + /** + * Creates an instance which generates a minimum spanning tree assuming constant edge weights. + */ + public PrimMinimumSpanningTree(Factory> factory) { + this(factory, new ConstantTransformer(1.0)); + } + + /** + * Creates an instance which generates a minimum spanning tree using the input edge weights. + */ + public PrimMinimumSpanningTree(Factory> factory, + Transformer weights) { + this.treeFactory = factory; + if(weights != null) { + this.weights = weights; + } + } + + /** + * @param graph the Graph to find MST in + */ + public Graph transform(Graph graph) { + Set unfinishedEdges = new HashSet(graph.getEdges()); + Graph tree = treeFactory.create(); + V root = findRoot(graph); + if(graph.getVertices().contains(root)) { + tree.addVertex(root); + } else if(graph.getVertexCount() > 0) { + // pick an arbitrary vertex to make root + tree.addVertex(graph.getVertices().iterator().next()); + } + updateTree(tree, graph, unfinishedEdges); + + return tree; + } + + protected V findRoot(Graph graph) { + for(V v : graph.getVertices()) { + if(graph.getInEdges(v).size() == 0) { + return v; + } + } + // if there is no obvious root, pick any vertex + if(graph.getVertexCount() > 0) { + return graph.getVertices().iterator().next(); + } + // this graph has no vertices + return null; + } + + protected void updateTree(Graph tree, Graph graph, Collection unfinishedEdges) { + Collection tv = tree.getVertices(); + double minCost = Double.MAX_VALUE; + E nextEdge = null; + V nextVertex = null; + V currentVertex = null; + for(E e : unfinishedEdges) { + + if(tree.getEdges().contains(e)) continue; + // find the lowest cost edge, get its opposite endpoint, + // and then update forest from its Successors + Pair endpoints = graph.getEndpoints(e); + V first = endpoints.getFirst(); + V second = endpoints.getSecond(); + if((tv.contains(first) == true && tv.contains(second) == false)) { + if(weights.transform(e) < minCost) { + minCost = weights.transform(e); + nextEdge = e; + currentVertex = first; + nextVertex = second; + } + } else if((tv.contains(second) == true && tv.contains(first) == false)) { + if(weights.transform(e) < minCost) { + minCost = weights.transform(e); + nextEdge = e; + currentVertex = second; + nextVertex = first; + } + } + } + + if(nextVertex != null && nextEdge != null) { + unfinishedEdges.remove(nextEdge); + tree.addEdge(nextEdge, currentVertex, nextVertex); + updateTree(tree, graph, unfinishedEdges); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPath.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPath.java new file mode 100644 index 0000000000..a922cdd329 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPath.java @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +* +* Created on Feb 12, 2004 +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Map; + + +/** + * An interface for algorithms that calculate shortest paths. + */ +public interface ShortestPath +{ + /** + *

        Returns a Map which maps each vertex + * in the graph (including the source vertex) + * to the last edge on the shortest path from the + * source vertex. + */ + Map getIncomingEdgeMap(V source); +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPathUtils.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPathUtils.java new file mode 100644 index 0000000000..d3e59ebec9 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPathUtils.java @@ -0,0 +1,54 @@ +/* + * Created on Jul 10, 2005 + * + * Copyright (c) 2005, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Utilities relating to the shortest paths in a graph. + */ +public class ShortestPathUtils +{ + /** + * Returns a List of the edges on the shortest path from + * source to target, in order of their + * occurrence on this path. + */ + public static List getPath(Graph graph, ShortestPath sp, V source, V target) + { + LinkedList path = new LinkedList(); + + Map incomingEdges = sp.getIncomingEdgeMap(source); + + if (incomingEdges.isEmpty() || incomingEdges.get(target) == null) + return path; + V current = target; + while (!current.equals(source)) + { + E incoming = incomingEdges.get(current); + path.addFirst(incoming); + Pair endpoints = graph.getEndpoints(incoming); + if(endpoints.getFirst().equals(current)) { + current = endpoints.getSecond(); + } else { + current = endpoints.getFirst(); + } + //incoming.getOpposite(current); + } + return path; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/UnweightedShortestPath.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/UnweightedShortestPath.java new file mode 100644 index 0000000000..1d3390c058 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/UnweightedShortestPath.java @@ -0,0 +1,151 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Computes the shortest path distances for graphs whose edges are not weighted (using BFS). + * + * @author Scott White + */ +public class UnweightedShortestPath + implements ShortestPath, Distance +{ + private Map> mDistanceMap; + private Map> mIncomingEdgeMap; + private Hypergraph mGraph; + private Map distances = new HashMap(); + + /** + * Constructs and initializes algorithm + * @param g the graph + */ + public UnweightedShortestPath(Hypergraph g) + { + mDistanceMap = new HashMap>(); + mIncomingEdgeMap = new HashMap>(); + mGraph = g; + } + + /** + * @see edu.uci.ics.jung.algorithms.shortestpath.Distance#getDistance(Object, Object) + */ + public Number getDistance(V source, V target) + { + Map sourceSPMap = getDistanceMap(source); + return sourceSPMap.get(target); + } + + /** + * @see edu.uci.ics.jung.algorithms.shortestpath.Distance#getDistanceMap(Object) + */ + public Map getDistanceMap(V source) + { + Map sourceSPMap = mDistanceMap.get(source); + if (sourceSPMap == null) + { + computeShortestPathsFromSource(source); + sourceSPMap = mDistanceMap.get(source); + } + return sourceSPMap; + } + + /** + * @see edu.uci.ics.jung.algorithms.shortestpath.ShortestPath#getIncomingEdgeMap(Object) + */ + public Map getIncomingEdgeMap(V source) + { + Map sourceIEMap = mIncomingEdgeMap.get(source); + if (sourceIEMap == null) + { + computeShortestPathsFromSource(source); + sourceIEMap = mIncomingEdgeMap.get(source); + } + return sourceIEMap; + } + + + /** + * Computes the shortest path distances from a given node to all other nodes. + * @param source the source node + */ + private void computeShortestPathsFromSource(V source) + { + BFSDistanceLabeler labeler = new BFSDistanceLabeler(); + labeler.labelDistances(mGraph, source); + distances = labeler.getDistanceDecorator(); + Map currentSourceSPMap = new HashMap(); + Map currentSourceEdgeMap = new HashMap(); + + for(V vertex : mGraph.getVertices()) { + + Number distanceVal = distances.get(vertex); + // BFSDistanceLabeler uses -1 to indicate unreachable vertices; + // don't bother to store unreachable vertices + if (distanceVal != null && distanceVal.intValue() >= 0) + { + currentSourceSPMap.put(vertex, distanceVal); + int minDistance = distanceVal.intValue(); + for(E incomingEdge : mGraph.getInEdges(vertex)) + { + for (V neighbor : mGraph.getIncidentVertices(incomingEdge)) + { + if (neighbor.equals(vertex)) + continue; +// V neighbor = mGraph.getOpposite(vertex, incomingEdge); + + Number predDistanceVal = distances.get(neighbor); + + int pred_distance = predDistanceVal.intValue(); + if (pred_distance < minDistance && pred_distance >= 0) + { + minDistance = predDistanceVal.intValue(); + currentSourceEdgeMap.put(vertex, incomingEdge); + } + } + } + } + } + mDistanceMap.put(source, currentSourceSPMap); + mIncomingEdgeMap.put(source, currentSourceEdgeMap); + } + + /** + * Clears all stored distances for this instance. + * Should be called whenever the graph is modified (edge weights + * changed or edges added/removed). If the user knows that + * some currently calculated distances are unaffected by a + * change, reset(V) may be appropriate instead. + * + * @see #reset(Object) + */ + public void reset() + { + mDistanceMap.clear(); + mIncomingEdgeMap.clear(); + } + + /** + * Clears all stored distances for the specified source vertex + * source. Should be called whenever the stored distances + * from this vertex are invalidated by changes to the graph. + * + * @see #reset() + */ + public void reset(V v) + { + mDistanceMap.remove(v); + mIncomingEdgeMap.remove(v); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/package.html new file mode 100644 index 0000000000..01f27b5f36 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/package.html @@ -0,0 +1,31 @@ + + + + + + + +Provides interfaces and classes for calculating (geodesic) distances and shortest paths. Currently includes: +

          +
        • DijkstraDistance: finds the distances from a specified source vertex to other vertices in a +weighted graph with no negative cycles +
        • DijkstraShortestPath: extends DijkstraDistance, also finds shortest paths +
        • Distance: an interface for defining vertex-vertex distances +
        • PrimMinimumSpanningTree: identifies the spanning tree for a graph of least total edge weight +
        • ShortestPath: an interface for shortest-path algorithms +
        • ShortestPathUtils: utility functions for manipulating shortest paths +
        • UnweightedShortestPath: finds the distances from a specified source vertex to other vertices in an +unweighted graph +
        + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/DirectionTransformer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/DirectionTransformer.java new file mode 100644 index 0000000000..8fa33b882d --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/DirectionTransformer.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +/* + * Created on Apr 21, 2004 + */ +package edu.uci.ics.jung.algorithms.transformation; + +import org.apache.commons.collections15.Factory; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + *

        Functions for transforming graphs into directed or undirected graphs.

        + * + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +public class DirectionTransformer +{ + + /** + * Transforms graph (which may be of any directionality) + * into an undirected graph. (This may be useful for + * visualization tasks). + * Specifically: + *
          + *
        • Vertices are copied from graph. + *
        • Directed edges are 'converted' into a single new undirected edge in the new graph. + *
        • Each undirected edge (if any) in graph is 'recreated' with a new undirected edge in the new + * graph if create_new is true, or copied from graph otherwise. + *
        + * + * @param graph the graph to be transformed + * @param create_new specifies whether existing undirected edges are to be copied or recreated + * @param graph_factory used to create the new graph object + * @param edge_factory used to create new edges + * @return the transformed Graph + */ + public static UndirectedGraph toUndirected(Graph graph, + Factory> graph_factory, + Factory edge_factory, boolean create_new) + { + UndirectedGraph out = graph_factory.create(); + + for (V v : graph.getVertices()) + out.addVertex(v); + + for (E e : graph.getEdges()) + { + Pair endpoints = graph.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + E to_add; + if (graph.getEdgeType(e) == EdgeType.DIRECTED || create_new) + to_add = edge_factory.create(); + else + to_add = e; + out.addEdge(to_add, v1, v2, EdgeType.UNDIRECTED); + } + return out; + } + + /** + * Transforms graph (which may be of any directionality) + * into a directed graph. + * Specifically: + *
          + *
        • Vertices are copied from graph. + *
        • Undirected edges are 'converted' into two new antiparallel directed edges in the new graph. + *
        • Each directed edge (if any) in graph is 'recreated' with a new edge in the new + * graph if create_new is true, or copied from graph otherwise. + *
        + * + * @param graph the graph to be transformed + * @param create_new specifies whether existing directed edges are to be copied or recreated + * @param graph_factory used to create the new graph object + * @param edge_factory used to create new edges + * @return the transformed Graph + */ + public static Graph toDirected(Graph graph, Factory> graph_factory, + Factory edge_factory, boolean create_new) + { + DirectedGraph out = graph_factory.create(); + + for (V v : graph.getVertices()) + out.addVertex(v); + + for (E e : graph.getEdges()) + { + Pair endpoints = graph.getEndpoints(e); + if (graph.getEdgeType(e) == EdgeType.UNDIRECTED) + { + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + out.addEdge(edge_factory.create(), v1, v2, EdgeType.DIRECTED); + out.addEdge(edge_factory.create(), v2, v1, EdgeType.DIRECTED); + } + else // if the edge is directed, just add it + { + V source = graph.getSource(e); + V dest = graph.getDest(e); + E to_add = create_new ? edge_factory.create() : e; + out.addEdge(to_add, source, dest, EdgeType.DIRECTED); + } + + } + return out; + } +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/FoldingTransformer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/FoldingTransformer.java new file mode 100644 index 0000000000..2193319484 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/FoldingTransformer.java @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +/* + * Created on Apr 21, 2004 + */ +package edu.uci.ics.jung.algorithms.transformation; + +import java.util.ArrayList; +import java.util.Collection; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.Predicate; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.KPartiteGraph; + +/** + * Methods for creating a "folded" graph based on a k-partite graph or a + * hypergraph. + * + *

        A "folded" graph is derived from a k-partite graph by identifying + * a partition of vertices which will become the vertices of the new graph, copying + * these vertices into the new graph, and then connecting those vertices whose + * original analogues were connected indirectly through elements + * of other partitions.

        + * + *

        A "folded" graph is derived from a hypergraph by creating vertices based on + * either the vertices or the hyperedges of the original graph, and connecting + * vertices in the new graph if their corresponding vertices/hyperedges share a + * connection with a common hyperedge/vertex.

        + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +public class FoldingTransformer +{ + + /** + * Converts g into a unipartite graph whose vertex set is the + * vertices of g's partition p. For vertices + * a and b in this partition, the resultant + * graph will include the edge (a,b) if the original graph + * contains edges (a,c) and (c,b) for at least + * one vertex c. + * + *

        The vertices of the new graph are the same as the vertices of the + * appropriate partition in the old graph; the edges in the new graph are + * created by the input edge Factory.

        + * + *

        If there is more than 1 such vertex c for a given pair + * (a,b), the type of the output graph will determine whether + * it will contain parallel edges or not.

        + * + *

        This function will not create self-loops.

        + * + * @param vertex type + * @param input edge type + * @param g input k-partite graph + * @param p predicate specifying vertex partition + * @param graph_factory factory used to create the output graph + * @param edge_factory factory used to create the edges in the new graph + * @return a copy of the input graph folded with respect to the input partition + */ + public static Graph foldKPartiteGraph(KPartiteGraph g, Predicate p, + Factory> graph_factory, Factory edge_factory) + { + Graph newGraph = graph_factory.create(); + + // get vertices for the specified partition + Collection vertices = g.getVertices(p); + for (V v : vertices) + { + newGraph.addVertex(v); + for (V s : g.getSuccessors(v)) + { + for (V t : g.getSuccessors(s)) + { + if (!vertices.contains(t) || t.equals(v)) + continue; + newGraph.addVertex(t); + newGraph.addEdge(edge_factory.create(), v, t); + } + } + } + return newGraph; + } + + /** + * Converts g into a unipartite graph whose vertices are the + * vertices of g's partition p, and whose edges + * consist of collections of the intermediate vertices from other partitions. + * For vertices + * a and b in this partition, the resultant + * graph will include the edge (a,b) if the original graph + * contains edges (a,c) and (c,b) for at least + * one vertex c. + * + *

        The vertices of the new graph are the same as the vertices of the + * appropriate partition in the old graph; the edges in the new graph are + * collections of the intermediate vertices c.

        + * + *

        This function will not create self-loops.

        + * + * @param vertex type + * @param input edge type + * @param g input k-partite graph + * @param p predicate specifying vertex partition + * @param graph_factory factory used to create the output graph + * @return the result of folding g into unipartite graph whose vertices + * are those of the p partition of g + */ + public static Graph> foldKPartiteGraph(KPartiteGraph g, Predicate p, + Factory>> graph_factory) + { + Graph> newGraph = graph_factory.create(); + + // get vertices for the specified partition, copy into new graph + Collection vertices = g.getVertices(p); + + for (V v : vertices) + { + newGraph.addVertex(v); + for (V s : g.getSuccessors(v)) + { + for (V t : g.getSuccessors(s)) + { + if (!vertices.contains(t) || t.equals(v)) + continue; + newGraph.addVertex(t); + Collection v_coll = newGraph.findEdge(v, t); + if (v_coll == null) + { + v_coll = new ArrayList(); + newGraph.addEdge(v_coll, v, t); + } + v_coll.add(s); + } + } + } + return newGraph; + } + + /** + * Creates a Graph which is an edge-folded version of h, where + * hyperedges are replaced by k-cliques in the output graph. + * + *

        The vertices of the new graph are the same objects as the vertices of + * h, and a + * is connected to b in the new graph if the corresponding vertices + * in h are connected by a hyperedge. Thus, each hyperedge with + * k vertices in h induces a k-clique in the new graph.

        + * + *

        The edges of the new graph consist of collections of each hyperedge that connected + * the corresponding vertex pair in the original graph.

        + * + * @param vertex type + * @param input edge type + * @param h hypergraph to be folded + * @param graph_factory factory used to generate the output graph + * @return a copy of the input graph where hyperedges are replaced by cliques + */ + public static Graph> foldHypergraphEdges(Hypergraph h, + Factory>> graph_factory) + { + Graph> target = graph_factory.create(); + + for (V v : h.getVertices()) + target.addVertex(v); + + for (E e : h.getEdges()) + { + ArrayList incident = new ArrayList(h.getIncidentVertices(e)); + populateTarget(target, e, incident); + } + return target; + } + + + /** + * Creates a Graph which is an edge-folded version of h, where + * hyperedges are replaced by k-cliques in the output graph. + * + *

        The vertices of the new graph are the same objects as the vertices of + * h, and a + * is connected to b in the new graph if the corresponding vertices + * in h are connected by a hyperedge. Thus, each hyperedge with + * k vertices in h induces a k-clique in the new graph.

        + * + *

        The edges of the new graph are generated by the specified edge factory.

        + * + * @param vertex type + * @param input edge type + * @param h hypergraph to be folded + * @param graph_factory factory used to generate the output graph + * @param edge_factory factory used to create the new edges + * @return a copy of the input graph where hyperedges are replaced by cliques + */ + public static Graph foldHypergraphEdges(Hypergraph h, + Factory> graph_factory, Factory edge_factory) + { + Graph target = graph_factory.create(); + + for (V v : h.getVertices()) + target.addVertex(v); + + for (E e : h.getEdges()) + { + ArrayList incident = new ArrayList(h.getIncidentVertices(e)); + for (int i = 0; i < incident.size(); i++) + for (int j = i+1; j < incident.size(); j++) + target.addEdge(edge_factory.create(), incident.get(i), incident.get(j)); + } + return target; + } + + /** + * Creates a Graph which is a vertex-folded version of h, whose + * vertices are the input's hyperedges and whose edges are induced by adjacent hyperedges + * in the input. + * + *

        The vertices of the new graph are the same objects as the hyperedges of + * h, and a + * is connected to b in the new graph if the corresponding edges + * in h have a vertex in common. Thus, each vertex incident to + * k edges in h induces a k-clique in the new graph.

        + * + *

        The edges of the new graph are created by the specified factory.

        + * + * @param vertex type + * @param input edge type + * @param output edge type + * @param h hypergraph to be folded + * @param graph_factory factory used to generate the output graph + * @param edge_factory factory used to generate the output edges + * @return a transformation of the input graph whose vertices correspond to the input's hyperedges + * and edges are induced by hyperedges sharing vertices in the input + */ + public static Graph foldHypergraphVertices(Hypergraph h, + Factory> graph_factory, Factory edge_factory) + { + Graph target = graph_factory.create(); + + for (E e : h.getEdges()) + target.addVertex(e); + + for (V v : h.getVertices()) + { + ArrayList incident = new ArrayList(h.getIncidentEdges(v)); + for (int i = 0; i < incident.size(); i++) + for (int j = i+1; j < incident.size(); j++) + target.addEdge(edge_factory.create(), incident.get(i), incident.get(j)); + } + + return target; + } + + /** + * Creates a Graph which is a vertex-folded version of h, whose + * vertices are the input's hyperedges and whose edges are induced by adjacent hyperedges + * in the input. + * + *

        The vertices of the new graph are the same objects as the hyperedges of + * h, and a + * is connected to b in the new graph if the corresponding edges + * in h have a vertex in common. Thus, each vertex incident to + * k edges in h induces a k-clique in the new graph.

        + * + *

        The edges of the new graph consist of collections of each vertex incident to + * the corresponding hyperedge pair in the original graph.

        + * + * @param h hypergraph to be folded + * @param graph_factory factory used to generate the output graph + * @return a transformation of the input graph whose vertices correspond to the input's hyperedges + * and edges are induced by hyperedges sharing vertices in the input + */ + public Graph> foldHypergraphVertices(Hypergraph h, + Factory>> graph_factory) + { + Graph> target = graph_factory.create(); + + for (E e : h.getEdges()) + target.addVertex(e); + + for (V v : h.getVertices()) + { + ArrayList incident = new ArrayList(h.getIncidentEdges(v)); + populateTarget(target, v, incident); + } + return target; + } + + /** + * @param target + * @param e + * @param incident + */ + private static void populateTarget(Graph> target, T e, + ArrayList incident) + { + for (int i = 0; i < incident.size(); i++) + { + S v1 = incident.get(i); + for (int j = i+1; j < incident.size(); j++) + { + S v2 = incident.get(j); + Collection e_coll = target.findEdge(v1, v2); + if (e_coll == null) + { + e_coll = new ArrayList(); + target.addEdge(e_coll, v1, v2); + } + e_coll.add(e); + } + } + } + +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/VertexPartitionCollapser.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/VertexPartitionCollapser.java new file mode 100644 index 0000000000..e44d05d446 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/VertexPartitionCollapser.java @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.transformation; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.collections15.Factory; +import org.apache.commons.collections15.Transformer; +import org.apache.commons.collections15.functors.MapTransformer; + +import edu.uci.ics.jung.algorithms.blockmodel.VertexPartition; +import edu.uci.ics.jung.graph.Graph; + +/** + * This class transforms a graph with a known vertex partitioning into a graph whose + * vertices correspond to the input graph's partitions. Two vertices in the output graph + * are connected if and only if there exists at least one edge between vertices in the + * corresponding partitions of the input graph. If the output graph permits parallel edges, + * there will be an edge connecting two vertices in the new graph for each such + * edge connecting constituent vertices in the input graph. + * + *

        Concept based on Danyel Fisher's GraphCollapser in JUNG 1.x. + * + */ +public class VertexPartitionCollapser +{ + protected Factory> graph_factory; + protected Factory vertex_factory; + protected Factory edge_factory; + protected Map, CV> set_collapsedv; + + /** + * Creates an instance with the specified graph and element factories. + * @param vertex_factory used to construct the vertices of the new graph + * @param edge_factory used to construct the edges of the new graph + * @param graph_factory used to construct the new graph + */ + public VertexPartitionCollapser(Factory> graph_factory, + Factory vertex_factory, Factory edge_factory) + { + this.graph_factory = graph_factory; + this.vertex_factory = vertex_factory; + this.edge_factory = edge_factory; + this.set_collapsedv = new HashMap, CV>(); + } + + /** + * Creates a new graph whose vertices correspond to the partitions of the supplied graph. + * @param partitioning + * @return a new graph whose vertices correspond to the partitions of the supplied graph + */ + public Graph collapseVertexPartitions(VertexPartition partitioning) + { + Graph original = partitioning.getGraph(); + Graph collapsed = graph_factory.create(); + + // create vertices in new graph corresponding to equivalence sets in the original graph + for (Set set : partitioning.getVertexPartitions()) + { + CV cv = vertex_factory.create(); + collapsed.addVertex(vertex_factory.create()); + set_collapsedv.put(set, cv); + } + + // create edges in new graph corresponding to edges in original graph + for (E e : original.getEdges()) + { + Collection incident = original.getIncidentVertices(e); + Collection collapsed_vertices = new HashSet(); + Map> vertex_partitions = partitioning.getVertexToPartitionMap(); + // collect the collapsed vertices corresponding to the original incident vertices + for (V v : incident) + collapsed_vertices.add(set_collapsedv.get(vertex_partitions.get(v))); + // if there's only one collapsed vertex, continue (no edges to create) + if (collapsed_vertices.size() > 1) + { + CE ce = edge_factory.create(); + collapsed.addEdge(ce, collapsed_vertices); + } + } + return collapsed; + } + + /** + * Returns a transformer from vertex sets in the original graph to collapsed vertices + * in the transformed graph. + */ + public Transformer, CV> getSetToCollapsedVertexTransformer() + { + return MapTransformer.getInstance(set_collapsedv); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/package.html new file mode 100644 index 0000000000..6680095fb1 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/transformation/package.html @@ -0,0 +1,29 @@ + + + + + + + +Mechanisms for graph transformation. These currently include: +

          +
        • DirectionTransformer: generates graphs where input undirected +edges have been converted to directed edges, or vice versa +
        • FoldingTransformer: transforms k-partite graphs or hypergraphs +into unipartite graphs +
        • VertexPartitionCollapser: transforms a graph, given a +partition of its vertices into disjoint sets, into a graph in which each +of these disjoint sets has been 'collapsed' into a single new vertex. +
        + + + diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/BasicMapEntry.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/BasicMapEntry.java new file mode 100644 index 0000000000..a82aea6b98 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/BasicMapEntry.java @@ -0,0 +1,80 @@ +package edu.uci.ics.jung.algorithms.util; + +import java.util.HashMap; +import java.util.Map; + +/** + * An simple minimal implementation of Map.Entry. + * + * @param the key type + * @param the value type + */ +public class BasicMapEntry implements Map.Entry { + final K key; + V value; + + /** + * Create new entry. + */ + public BasicMapEntry(K k, V v) { + value = v; + key = k; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V newValue) { + V oldValue = value; + value = newValue; + return oldValue; + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry e = (Map.Entry)o; + Object k1 = getKey(); + Object k2 = e.getKey(); + if (k1 == k2 || (k1 != null && k1.equals(k2))) { + Object v1 = getValue(); + Object v2 = e.getValue(); + if (v1 == v2 || (v1 != null && v1.equals(v2))) + return true; + } + return false; + } + + @Override + public int hashCode() { + return (key==null ? 0 : key.hashCode()) ^ + (value==null ? 0 : value.hashCode()); + } + + @Override + public String toString() { + return getKey() + "=" + getValue(); + } + + /** + * This method is invoked whenever the value in an entry is + * overwritten by an invocation of put(k,v) for a key k that's already + * in the HashMap. + */ + void recordAccess(HashMap m) { + } + + /** + * This method is invoked whenever the entry is + * removed from the table. + */ + void recordRemoval(HashMap m) { + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/ConstantMap.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/ConstantMap.java new file mode 100644 index 0000000000..53054d71d9 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/ConstantMap.java @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ + +package edu.uci.ics.jung.algorithms.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + * An implementation of Map that returns the constructor-supplied + * value for any input. + * + * @param the key type + * @param the value type + */ +public class ConstantMap implements Map { + + private Map delegate; + + /** + * Creates an instance whose {@code get} method always returns {@code value}. + */ + public ConstantMap(V value) { + delegate = Collections.unmodifiableMap(Collections.singletonMap(null, value)); + } + + public V get(Object key) { + return delegate.get(null); + } + + public void clear() { + delegate.clear(); + } + + public boolean containsKey(Object key) { + return true; + } + + public boolean containsValue(Object value) { + return delegate.containsValue(value); + } + + public Set> entrySet() { + return delegate.entrySet(); + } + + @Override + public boolean equals(Object o) { + return delegate.equals(o); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + public boolean isEmpty() { + return delegate.isEmpty(); + } + + public Set keySet() { + return delegate.keySet(); + } + + public V put(K key, V value) { + return delegate.put(key, value); + } + + public void putAll(Map t) { + delegate.putAll(t); + } + + public V remove(Object key) { + return delegate.remove(key); + } + + public int size() { + return delegate.size(); + } + + public Collection values() { + return delegate.values(); + } +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/DiscreteDistribution.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/DiscreteDistribution.java new file mode 100644 index 0000000000..84eadc0735 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/DiscreteDistribution.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * + * Created on Feb 18, 2004 + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.Collection; +import java.util.Iterator; + +/** + * A utility class for calculating properties of discrete distributions. + * Generally, these distributions are represented as arrays of + * double values, which are assumed to be normalized + * such that the entries in a single array sum to 1. + * + * @author Joshua O'Madadhain + */ +public class DiscreteDistribution +{ + + /** + * Returns the Kullback-Leibler divergence between the + * two specified distributions, which must have the same + * number of elements. This is defined as + * the sum over all i of + * dist[i] * Math.log(dist[i] / reference[i]). + * Note that this value is not symmetric; see + * symmetricKL for a symmetric variant. + * @see #symmetricKL(double[], double[]) + */ + public static double KullbackLeibler(double[] dist, double[] reference) + { + double distance = 0; + + checkLengths(dist, reference); + + for (int i = 0; i < dist.length; i++) + { + if (dist[i] > 0 && reference[i] > 0) + distance += dist[i] * Math.log(dist[i] / reference[i]); + } + return distance; + } + + /** + * Returns KullbackLeibler(dist, reference) + KullbackLeibler(reference, dist). + * @see #KullbackLeibler(double[], double[]) + */ + public static double symmetricKL(double[] dist, double[] reference) + { + return KullbackLeibler(dist, reference) + + KullbackLeibler(reference, dist); + } + + /** + * Returns the squared difference between the + * two specified distributions, which must have the same + * number of elements. This is defined as + * the sum over all i of the square of + * (dist[i] - reference[i]). + */ + public static double squaredError(double[] dist, double[] reference) + { + double error = 0; + + checkLengths(dist, reference); + + for (int i = 0; i < dist.length; i++) + { + double difference = dist[i] - reference[i]; + error += difference * difference; + } + return error; + } + + /** + * Returns the cosine distance between the two + * specified distributions, which must have the same number + * of elements. The distributions are treated as vectors + * in dist.length-dimensional space. + * Given the following definitions + *
          + *
        • v = the sum over all i of dist[i] * dist[i] + *
        • w = the sum over all i of reference[i] * reference[i] + *
        • vw = the sum over all i of dist[i] * reference[i] + *
        + * the value returned is defined as vw / (Math.sqrt(v) * Math.sqrt(w)). + */ + public static double cosine(double[] dist, double[] reference) + { + double v_prod = 0; // dot product x*x + double w_prod = 0; // dot product y*y + double vw_prod = 0; // dot product x*y + + checkLengths(dist, reference); + + for (int i = 0; i < dist.length; i++) + { + vw_prod += dist[i] * reference[i]; + v_prod += dist[i] * dist[i]; + w_prod += reference[i] * reference[i]; + } + // cosine distance between v and w + return vw_prod / (Math.sqrt(v_prod) * Math.sqrt(w_prod)); + } + + /** + * Returns the entropy of this distribution. + * High entropy indicates that the distribution is + * close to uniform; low entropy indicates that the + * distribution is close to a Dirac delta (i.e., if + * the probability mass is concentrated at a single + * point, this method returns 0). Entropy is defined as + * the sum over all i of + * -(dist[i] * Math.log(dist[i])) + */ + public static double entropy(double[] dist) + { + double total = 0; + + for (int i = 0; i < dist.length; i++) + { + if (dist[i] > 0) + total += dist[i] * Math.log(dist[i]); + } + return -total; + } + + /** + * Throws an IllegalArgumentException if the two arrays are not of the same length. + */ + protected static void checkLengths(double[] dist, double[] reference) + { + if (dist.length != reference.length) + throw new IllegalArgumentException("Arrays must be of the same length"); + } + + /** + * Normalizes, with Lagrangian smoothing, the specified double + * array, so that the values sum to 1 (i.e., can be treated as probabilities). + * The effect of the Lagrangian smoothing is to ensure that all entries + * are nonzero; effectively, a value of alpha is added to each + * entry in the original array prior to normalization. + * @param counts + * @param alpha + */ + public static void normalize(double[] counts, double alpha) + { + double total_count = 0; + + for (int i = 0; i < counts.length; i++) + total_count += counts[i]; + + for (int i = 0; i < counts.length; i++) + counts[i] = (counts[i] + alpha) + / (total_count + counts.length * alpha); + } + + /** + * Returns the mean of the specified Collection of + * distributions, which are assumed to be normalized arrays of + * double values. + * @see #mean(double[][]) + */ + public static double[] mean(Collection distributions) + { + if (distributions.isEmpty()) + throw new IllegalArgumentException("Distribution collection must be non-empty"); + Iterator iter = distributions.iterator(); + double[] first = iter.next(); + double[][] d_array = new double[distributions.size()][first.length]; + d_array[0] = first; + for (int i = 1; i < d_array.length; i++) + d_array[i] = iter.next(); + + return mean(d_array); + } + + /** + * Returns the mean of the specified array of distributions, + * represented as normalized arrays of double values. + * Will throw an "index out of bounds" exception if the + * distribution arrays are not all of the same length. + */ + public static double[] mean(double[][] distributions) + { + double[] d_mean = new double[distributions[0].length]; + for (int j = 0; j < d_mean.length; j++) + d_mean[j] = 0; + + for (int i = 0; i < distributions.length; i++) + for (int j = 0; j < d_mean.length; j++) + d_mean[j] += distributions[i][j] / distributions.length; + + return d_mean; + } + +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/Indexer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/Indexer.java new file mode 100644 index 0000000000..b8a215e3d5 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/Indexer.java @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.util; + +import java.util.Collection; + +import org.apache.commons.collections15.BidiMap; +import org.apache.commons.collections15.bidimap.DualHashBidiMap; + +/** + * A class providing static methods useful for improving the + * performance of graph algorithms. + * + * @author Tom Nelson + * + */ +public class Indexer { + + /** + * Returns a BidiMap mapping each element of the collection to its + * index as encountered while iterating over the collection. The purpose + * of the index operation is to supply an O(1) replacement operation for the + * O(n) indexOf(element) method of a List + * @param + * @param collection + * @return a bidirectional map from collection elements to 0-based indices + */ + public static BidiMap create(Collection collection) { + return create(collection, 0); + } + /** + * Returns a BidiMap mapping each element of the collection to its + * index as encountered while iterating over the collection. The purpose + * of the index operation is to supply an O(1) replacement operation for the + * O(n) indexOf(element) method of a List + * @param + * @param collection + * @param start start index + * @return a bidirectional map from collection elements to start-based indices + */ + public static BidiMap create(Collection collection, int start) { + BidiMap map = new DualHashBidiMap(); + int i=start; + for(T t : collection) { + map.put(t,i++); + } + return map; + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeContext.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeContext.java new file mode 100644 index 0000000000..92bd45d3f4 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeContext.java @@ -0,0 +1,28 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.util; + + +/** + * An interface for algorithms that proceed iteratively. + * + */ +public interface IterativeContext +{ + /** + * Advances one step. + */ + void step(); + + /** + * Returns true if this iterative process is finished, and false otherwise. + */ + boolean done(); +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeProcess.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeProcess.java new file mode 100644 index 0000000000..fbe07f4e86 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeProcess.java @@ -0,0 +1,174 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package edu.uci.ics.jung.algorithms.util; + + + +/** + * Provides basic infrastructure for iterative algorithms. Services provided include: + *
          + *
        • storage of current and max iteration count
        • + *
        • framework for initialization, iterative evaluation, and finalization
        • + *
        • test for convergence
        • + *
        • etc.
        • + *
        + *

        + * Algorithms that subclass this class are typically used in the following way:
        + *

        + * FooAlgorithm foo = new FooAlgorithm(...)
        + * foo.setMaximumIterations(100); //set up conditions
        + * ...
        + * foo.evaluate(); //key method which initiates iterative process
        + * foo.getSomeResult();
        + * 
        + * + * @author Scott White (originally written by Didier Besset) + */ +public abstract class IterativeProcess implements IterativeContext { + /** + * Number of iterations performed. + */ + private int iterations; + /** + * Maximum allowed number of iterations. + */ + private int maximumIterations = 50; + /** + * Desired precision. + */ + private double desiredPrecision = Double.MIN_VALUE; + /** + * Achieved precision. + */ + private double precision; + + + /** + * Generic constructor. + */ + public IterativeProcess() { + } + + /** + * Performs the iterative process. + * Note: this method does not return anything because Java does not + * allow mixing double, int, or objects + */ + public void evaluate() { + iterations = 0; + initializeIterations(); + while (iterations++ < maximumIterations) { + step(); + precision = getPrecision(); + if (hasConverged()) + break; + } + finalizeIterations(); + } + + /** + * Evaluate the result of the current iteration. + */ + abstract public void step(); + + /** + * Perform eventual clean-up operations + * (must be implement by subclass when needed). + */ + protected void finalizeIterations() { + } + + /** + * Returns the desired precision. + */ + public double getDesiredPrecision() { + return desiredPrecision; + } + + /** + * Returns the number of iterations performed. + */ + public int getIterations() { + return iterations; + } + + /** + * Returns the maximum allowed number of iterations. + */ + public int getMaximumIterations() { + return maximumIterations; + } + + /** + * Returns the attained precision. + */ + public double getPrecision() { + return precision; + } + + /** + * @param precision the precision to set + */ + public void setPrecision(double precision) { + this.precision = precision; + } + + /** + * + * Check to see if the result has been attained. + * @return boolean + */ + public boolean hasConverged() { + return precision < desiredPrecision; + } + + public boolean done() { + return hasConverged(); + } + + /** + * Initializes internal parameters to start the iterative process. + */ + protected void initializeIterations() { + } + + /** + * + */ + public void reset() { + } + + /** + * @return double + * @param epsilon double + * @param x double + */ + public double relativePrecision(double epsilon, double x) { + return x > desiredPrecision ? epsilon / x: epsilon; + } + + /** + * Defines the desired precision. + */ + public void setDesiredPrecision(double prec) throws IllegalArgumentException { + if (prec <= 0) + throw new IllegalArgumentException("Non-positive precision: " + prec); + desiredPrecision = prec; + } + + /** + * Defines the maximum allowed number of iterations. + */ + public void setMaximumIterations(int maxIter) throws IllegalArgumentException { + if (maxIter < 1) + throw new IllegalArgumentException("Non-positive maximum iteration: " + maxIter); + maximumIterations = maxIter; + } +} \ No newline at end of file diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/KMeansClusterer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/KMeansClusterer.java new file mode 100644 index 0000000000..dce550f477 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/KMeansClusterer.java @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +/* + * Created on Aug 9, 2004 + * + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Random; +import java.util.Set; + + + +/** + * Groups items into a specified number of clusters, based on their proximity in + * d-dimensional space, using the k-means algorithm. Calls to + * cluster will terminate when either of the two following + * conditions is true: + *
          + *
        • the number of iterations is > max_iterations + *
        • none of the centroids has moved as much as convergence_threshold + * since the previous iteration + *
        + * + * @author Joshua O'Madadhain + */ +public class KMeansClusterer +{ + protected int max_iterations; + protected double convergence_threshold; + protected Random rand; + + /** + * Creates an instance whose termination conditions are set according + * to the parameters. + */ + public KMeansClusterer(int max_iterations, double convergence_threshold) + { + this.max_iterations = max_iterations; + this.convergence_threshold = convergence_threshold; + this.rand = new Random(); + } + + /** + * Creates an instance with max iterations of 100 and convergence threshold + * of 0.001. + */ + public KMeansClusterer() + { + this(100, 0.001); + } + + /** + * Returns the maximum number of iterations. + */ + public int getMaxIterations() + { + return max_iterations; + } + + /** + * Sets the maximum number of iterations. + */ + public void setMaxIterations(int max_iterations) + { + if (max_iterations < 0) + throw new IllegalArgumentException("max iterations must be >= 0"); + + this.max_iterations = max_iterations; + } + + /** + * Returns the convergence threshold. + */ + public double getConvergenceThreshold() + { + return convergence_threshold; + } + + /** + * Sets the convergence threshold. + * @param convergence_threshold + */ + public void setConvergenceThreshold(double convergence_threshold) + { + if (convergence_threshold <= 0) + throw new IllegalArgumentException("convergence threshold " + + "must be > 0"); + + this.convergence_threshold = convergence_threshold; + } + + /** + * Returns a Collection of clusters, where each cluster is + * represented as a Map of Objects to locations + * in d-dimensional space. + * @param object_locations a map of the Objects to cluster, to + * double arrays that specify their locations in d-dimensional space. + * @param num_clusters the number of clusters to create + * @throws NotEnoughClustersException + */ + @SuppressWarnings("unchecked") + public Collection> cluster(Map object_locations, int num_clusters) + { + if (object_locations == null || object_locations.isEmpty()) + throw new IllegalArgumentException("'objects' must be non-empty"); + + if (num_clusters < 2 || num_clusters > object_locations.size()) + throw new IllegalArgumentException("number of clusters " + + "must be >= 2 and <= number of objects (" + + object_locations.size() + ")"); + + + Set centroids = new HashSet(); + + Object[] obj_array = object_locations.keySet().toArray(); + Set tried = new HashSet(); + + // create the specified number of clusters + while (centroids.size() < num_clusters && tried.size() < object_locations.size()) + { + T o = (T)obj_array[(int)(rand.nextDouble() * obj_array.length)]; + tried.add(o); + double[] mean_value = object_locations.get(o); + boolean duplicate = false; + for (double[] cur : centroids) + { + if (Arrays.equals(mean_value, cur)) + duplicate = true; + } + if (!duplicate) + centroids.add(mean_value); + } + + if (tried.size() >= object_locations.size()) + throw new NotEnoughClustersException(); + + // put items in their initial clusters + Map> clusterMap = assignToClusters(object_locations, centroids); + + // keep reconstituting clusters until either + // (a) membership is stable, or + // (b) number of iterations passes max_iterations, or + // (c) max movement of any centroid is <= convergence_threshold + int iterations = 0; + double max_movement = Double.POSITIVE_INFINITY; + while (iterations++ < max_iterations && max_movement > convergence_threshold) + { + max_movement = 0; + Set new_centroids = new HashSet(); + // calculate new mean for each cluster + for (Map.Entry> entry : clusterMap.entrySet()) + { + double[] centroid = entry.getKey(); + Map elements = entry.getValue(); + ArrayList locations = new ArrayList(elements.values()); + + double[] mean = DiscreteDistribution.mean(locations); + max_movement = Math.max(max_movement, + Math.sqrt(DiscreteDistribution.squaredError(centroid, mean))); + new_centroids.add(mean); + } + + // TODO: check membership of clusters: have they changed? + + // regenerate cluster membership based on means + clusterMap = assignToClusters(object_locations, new_centroids); + } + return clusterMap.values(); + } + + /** + * Assigns each object to the cluster whose centroid is closest to the + * object. + * @param object_locations a map of objects to locations + * @param centroids the centroids of the clusters to be formed + * @return a map of objects to assigned clusters + */ + protected Map> assignToClusters(Map object_locations, Set centroids) + { + Map> clusterMap = new HashMap>(); + for (double[] centroid : centroids) + clusterMap.put(centroid, new HashMap()); + + for (Map.Entry object_location : object_locations.entrySet()) + { + T object = object_location.getKey(); + double[] location = object_location.getValue(); + + // find the cluster with the closest centroid + Iterator c_iter = centroids.iterator(); + double[] closest = c_iter.next(); + double distance = DiscreteDistribution.squaredError(location, closest); + + while (c_iter.hasNext()) + { + double[] centroid = c_iter.next(); + double dist_cur = DiscreteDistribution.squaredError(location, centroid); + if (dist_cur < distance) + { + distance = dist_cur; + closest = centroid; + } + } + clusterMap.get(closest).put(object, location); + } + + return clusterMap; + } + + /** + * Sets the seed used by the internal random number generator. + * Enables consistent outputs. + */ + public void setSeed(int random_seed) + { + this.rand = new Random(random_seed); + } + + /** + * An exception that indicates that the specified data points cannot be + * clustered into the number of clusters requested by the user. + * This will happen if and only if there are fewer distinct points than + * requested clusters. (If there are fewer total data points than + * requested clusters, IllegalArgumentException will be thrown.) + * + * @author Joshua O'Madadhain + */ + @SuppressWarnings("serial") + public static class NotEnoughClustersException extends RuntimeException + { + @Override + public String getMessage() + { + return "Not enough distinct points in the input data set to form " + + "the requested number of clusters"; + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/MapBinaryHeap.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/MapBinaryHeap.java new file mode 100644 index 0000000000..bd00a82810 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/MapBinaryHeap.java @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +/* + * + * Created on Oct 29, 2003 + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Vector; + +import org.apache.commons.collections15.IteratorUtils; + +/** + * An array-based binary heap implementation of a priority queue, + * which also provides + * efficient update() and contains operations. + * It contains extra infrastructure (a hash table) to keep track of the + * position of each element in the array; thus, if the key value of an element + * changes, it may be "resubmitted" to the heap via update + * so that the heap can reposition it efficiently, as necessary. + * + * @author Joshua O'Madadhain + */ +public class MapBinaryHeap + extends AbstractCollection + implements Queue +{ + private Vector heap = new Vector(); // holds the heap as an implicit binary tree + private Map object_indices = new HashMap(); // maps each object in the heap to its index in the heap + private Comparator comp; + private final static int TOP = 0; // the index of the top of the heap + + /** + * Creates a MapBinaryHeap whose heap ordering + * is based on the ordering of the elements specified by c. + */ + public MapBinaryHeap(Comparator comp) + { + initialize(comp); + } + + /** + * Creates a MapBinaryHeap whose heap ordering + * will be based on the natural ordering of the elements, + * which must be Comparable. + */ + public MapBinaryHeap() + { + initialize(new ComparableComparator()); + } + + /** + * Creates a MapBinaryHeap based on the specified + * collection whose heap ordering + * will be based on the natural ordering of the elements, + * which must be Comparable. + */ + public MapBinaryHeap(Collection c) + { + this(); + addAll(c); + } + + /** + * Creates a MapBinaryHeap based on the specified collection + * whose heap ordering + * is based on the ordering of the elements specified by c. + */ + public MapBinaryHeap(Collection c, Comparator comp) + { + this(comp); + addAll(c); + } + + private void initialize(Comparator comp) + { + this.comp = comp; + clear(); + } + + /** + * @see Collection#clear() + */ + @Override + public void clear() + { + object_indices.clear(); + heap.clear(); + } + + /** + * Inserts o into this collection. + */ + @Override + public boolean add(T o) + { + int i = heap.size(); // index 1 past the end of the heap + heap.setSize(i+1); + percolateUp(i, o); + return true; + } + + /** + * Returns true if this collection contains no elements, and + * false otherwise. + */ + @Override + public boolean isEmpty() + { + return heap.isEmpty(); + } + + /** + * Returns the element at the top of the heap; does not + * alter the heap. + */ + public T peek() + { + if (heap.size() > 0) + return heap.elementAt(TOP); + else + return null; + } + + /** + * Removes the element at the top of this heap, and returns it. + * @deprecated Use {@link MapBinaryHeap#poll()} + * or {@link MapBinaryHeap#remove()} instead. + */ + @Deprecated + public T pop() throws NoSuchElementException + { + return this.remove(); + } + + /** + * Returns the size of this heap. + */ + @Override + public int size() + { + return heap.size(); + } + + /** + * Informs the heap that this object's internal key value has been + * updated, and that its place in the heap may need to be shifted + * (up or down). + * @param o + */ + public void update(T o) + { + // Since we don't know whether the key value increased or + // decreased, we just percolate up followed by percolating down; + // one of the two will have no effect. + + int cur = object_indices.get(o).intValue(); // current index + int new_idx = percolateUp(cur, o); + percolateDown(new_idx); + } + + /** + * @see Collection#contains(java.lang.Object) + */ + @Override + public boolean contains(Object o) + { + return object_indices.containsKey(o); + } + + /** + * Moves the element at position cur closer to + * the bottom of the heap, or returns if no further motion is + * necessary. Calls itself recursively if further motion is + * possible. + */ + private void percolateDown(int cur) + { + int left = lChild(cur); + int right = rChild(cur); + int smallest; + + if ((left < heap.size()) && + (comp.compare(heap.elementAt(left), heap.elementAt(cur)) < 0)) { + smallest = left; + } else { + smallest = cur; + } + + if ((right < heap.size()) && + (comp.compare(heap.elementAt(right), heap.elementAt(smallest)) < 0)) { + smallest = right; + } + + if (cur != smallest) + { + swap(cur, smallest); + percolateDown(smallest); + } + } + + /** + * Moves the element o at position cur + * as high as it can go in the heap. Returns the new position of the + * element in the heap. + */ + private int percolateUp(int cur, T o) + { + int i = cur; + + while ((i > TOP) && (comp.compare(heap.elementAt(parent(i)), o) > 0)) + { + T parentElt = heap.elementAt(parent(i)); + heap.setElementAt(parentElt, i); + object_indices.put(parentElt, new Integer(i)); // reset index to i (new location) + i = parent(i); + } + + // place object in heap at appropriate place + object_indices.put(o, new Integer(i)); + heap.setElementAt(o, i); + + return i; + } + + /** + * Returns the index of the left child of the element at + * index i of the heap. + * @param i + * @return the index of the left child of the element at + * index i of the heap + */ + private int lChild(int i) + { + return (i<<1) + 1; + } + + /** + * Returns the index of the right child of the element at + * index i of the heap. + * @param i + * @return the index of the right child of the element at + * index i of the heap + */ + private int rChild(int i) + { + return (i<<1) + 2; + } + + /** + * Returns the index of the parent of the element at + * index i of the heap. + * @param i + * @return the index of the parent of the element at index i of the heap + */ + private int parent(int i) + { + return (i-1)>>1; + } + + /** + * Swaps the positions of the elements at indices i + * and j of the heap. + * @param i + * @param j + */ + private void swap(int i, int j) + { + T iElt = heap.elementAt(i); + T jElt = heap.elementAt(j); + + heap.setElementAt(jElt, i); + object_indices.put(jElt, new Integer(i)); + + heap.setElementAt(iElt, j); + object_indices.put(iElt, new Integer(j)); + } + + /** + * Comparator used if none is specified in the constructor. + * @author Joshua O'Madadhain + */ + private class ComparableComparator implements Comparator + { + /** + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @SuppressWarnings("unchecked") + public int compare(T arg0, T arg1) + { + if (!(arg0 instanceof Comparable) || !(arg1 instanceof Comparable)) + throw new IllegalArgumentException("Arguments must be Comparable"); + + return ((Comparable)arg0).compareTo(arg1); + } + } + + /** + * Returns an Iterator that does not support modification + * of the heap. + */ + @Override + public Iterator iterator() + { + return IteratorUtils.unmodifiableIterator(heap.iterator()); + } + + /** + * This data structure does not support the removal of arbitrary elements. + */ + @Override + public boolean remove(Object o) + { + throw new UnsupportedOperationException(); + } + + /** + * This data structure does not support the removal of arbitrary elements. + */ + @Override + public boolean removeAll(Collection c) + { + throw new UnsupportedOperationException(); + } + + /** + * This data structure does not support the removal of arbitrary elements. + */ + @Override + public boolean retainAll(Collection c) + { + throw new UnsupportedOperationException(); + } + + public T element() throws NoSuchElementException + { + T top = this.peek(); + if (top == null) + throw new NoSuchElementException(); + return top; + } + + public boolean offer(T o) + { + return add(o); + } + + public T poll() + { + T top = this.peek(); + if (top != null) + { + T bottom_elt = heap.lastElement(); + heap.setElementAt(bottom_elt, TOP); + object_indices.put(bottom_elt, new Integer(TOP)); + + heap.setSize(heap.size() - 1); // remove the last element + if (heap.size() > 1) + percolateDown(TOP); + + object_indices.remove(top); + } + return top; + } + + public T remove() + { + T top = this.poll(); + if (top == null) + throw new NoSuchElementException(); + return top; + } + +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/MapSettableTransformer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/MapSettableTransformer.java new file mode 100644 index 0000000000..1aa7d50709 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/MapSettableTransformer.java @@ -0,0 +1,44 @@ +/* + * Created on Aug 5, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.Map; + + +/** + * A SettableTransformer that operates on an underlying Map instance. + * Similar to MapTransformer. + * + * @author Joshua O'Madadhain + */ +public class MapSettableTransformer implements SettableTransformer +{ + protected Map map; + + /** + * Creates an instance based on m. + */ + public MapSettableTransformer(Map m) + { + this.map = m; + } + + public O transform(I input) + { + return map.get(input); + } + + public void set(I input, O output) + { + map.put(input, output); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java new file mode 100644 index 0000000000..a92c3b8d43 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java @@ -0,0 +1,23 @@ +package edu.uci.ics.jung.algorithms.util; + +import org.apache.commons.collections15.Predicate; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * A Predicate that returns true if the input edge's + * endpoints in the input graph are identical. (Thus, an edge which connects + * its sole incident vertex to itself). + * + * @param + * @param + */ +public class SelfLoopEdgePredicate implements Predicate,E>> { + + public boolean evaluate(Context,E> context) { + Pair endpoints = context.graph.getEndpoints(context.element); + return endpoints.getFirst().equals(endpoints.getSecond()); + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/SettableTransformer.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/SettableTransformer.java new file mode 100644 index 0000000000..5e5168abf1 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/SettableTransformer.java @@ -0,0 +1,31 @@ +/* + * Created on Aug 5, 2007 + * + * Copyright (c) 2007, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + */ +package edu.uci.ics.jung.algorithms.util; + +import org.apache.commons.collections15.Transformer; + +/** + * An interface for classes that can set the value to be returned (from transform()) + * when invoked on a given input. + * + * @author Joshua O'Madadhain + */ +public interface SettableTransformer extends Transformer +{ + /** + * Sets the value (output) to be returned by a call to + * transform(input)). + * @param input + * @param output + */ + public void set(I input, O output); +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/WeightedChoice.java b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/WeightedChoice.java new file mode 100644 index 0000000000..d9590b26a6 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/WeightedChoice.java @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2009, the JUNG Project and the Regents of the University + * of California + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * http://jung.sourceforge.net/license.txt for a description. + * Created on Jan 8, 2009 + * + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Random; + +/** + * Selects items according to their probability in an arbitrary probability + * distribution. The distribution is specified by a {@code Map} from + * items (of type {@code T}) to weights of type {@code Number}, supplied + * to the constructor; these weights are normalized internally to act as + * probabilities. + * + *

        This implementation selects items in O(1) time, and requires O(n) space. + * + * @author Joshua O'Madadhain + */ +public class WeightedChoice +{ + private List item_pairs; + private Random random; + + /** + * The default minimum value that is treated as a valid probability + * (as opposed to rounding error from floating-point operations). + */ + public static final double DEFAULT_THRESHOLD = 0.00000000001; + + /** + * Equivalent to {@code this(item_weights, new Random(), DEFAULT_THRESHOLD)}. + * @param item_weights + */ + public WeightedChoice(Map item_weights) + { + this(item_weights, new Random(), DEFAULT_THRESHOLD); + } + + /** + * Equivalent to {@code this(item_weights, new Random(), threshold)}. + */ + public WeightedChoice(Map item_weights, double threshold) + { + this(item_weights, new Random(), threshold); + } + + /** + * Equivalent to {@code this(item_weights, random, DEFAULT_THRESHOLD)}. + */ + public WeightedChoice(Map item_weights, Random random) + { + this(item_weights, random, DEFAULT_THRESHOLD); + } + + /** + * Creates an instance with the specified mapping from items to weights, + * random number generator, and threshold value. + * + *

        The mapping defines the weight for each item to be selected; this + * will be proportional to the probability of its selection. + *

        The random number generator specifies the mechanism which will be + * used to provide uniform integer and double values. + *

        The threshold indicates default minimum value that is treated as a valid + * probability (as opposed to rounding error from floating-point operations). + */ + public WeightedChoice(Map item_weights, Random random, + double threshold) + { + if (item_weights.isEmpty()) + throw new IllegalArgumentException("Item weights must be non-empty"); + + int item_count = item_weights.size(); + item_pairs = new ArrayList(item_count); + + double sum = 0; + for (Map.Entry entry : item_weights.entrySet()) + { + double value = entry.getValue().doubleValue(); + if (value <= 0) + throw new IllegalArgumentException("Weights must be > 0"); + sum += value; + } + double bucket_weight = 1.0 / item_weights.size(); + + Queue light_weights = new LinkedList(); + Queue heavy_weights = new LinkedList(); + for (Map.Entry entry : item_weights.entrySet()) + { + double value = entry.getValue().doubleValue() / sum; + enqueueItem(entry.getKey(), value, bucket_weight, light_weights, heavy_weights); + } + + // repeat until both queues empty + while (!heavy_weights.isEmpty() || !light_weights.isEmpty()) + { + ItemPair heavy_item = heavy_weights.poll(); + ItemPair light_item = light_weights.poll(); + double light_weight = 0; + T light = null; + T heavy = null; + if (light_item != null) + { + light_weight = light_item.weight; + light = light_item.light; + } + if (heavy_item != null) + { + heavy = heavy_item.heavy; + // put the 'left over' weight from the heavy item--what wasn't + // needed to make up the difference between the light weight and + // 1/n--back in the appropriate queue + double new_weight = heavy_item.weight - (bucket_weight - light_weight); + if (new_weight > threshold) + enqueueItem(heavy, new_weight, bucket_weight, light_weights, heavy_weights); + } + light_weight *= item_count; + + item_pairs.add(new ItemPair(light, heavy, light_weight)); + } + + this.random = random; + } + + /** + * Adds key/value to the appropriate queue. Keys with values less than + * the threshold get added to {@code light_weights}, all others get added + * to {@code heavy_weights}. + */ + private void enqueueItem(T key, double value, double threshold, + Queue light_weights, Queue heavy_weights) + { + if (value < threshold) + light_weights.offer(new ItemPair(key, null, value)); + else + heavy_weights.offer(new ItemPair(null, key, value)); + } + + /** + * Sets the seed used by the internal random number generator. + */ + public void setRandomSeed(long seed) + { + this.random.setSeed(seed); + } + + /** + * Retrieves an item with probability proportional to its weight in the + * {@code Map} provided in the input. + */ + public T nextItem() + { + ItemPair item_pair = item_pairs.get(random.nextInt(item_pairs.size())); + if (random.nextDouble() < item_pair.weight) + return item_pair.light; + return item_pair.heavy; + } + + /** + * Manages light object/heavy object/light conditional probability tuples. + */ + private class ItemPair + { + T light; + T heavy; + double weight; + + private ItemPair(T light, T heavy, double weight) + { + this.light = light; + this.heavy = heavy; + this.weight = weight; + } + + @Override + public String toString() + { + return String.format("[L:%s, H:%s, %.3f]", light, heavy, weight); + } + } +} diff --git a/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/package.html b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/package.html new file mode 100644 index 0000000000..58c5f591f0 --- /dev/null +++ b/third-party/net.sf.jung2/src/main/java/edu/uci/ics/jung/algorithms/util/package.html @@ -0,0 +1,32 @@ + + + + + + + +Provides general algorithmic utilities. These include: +

          +
        • DiscreteDistribution: calculates statistical measures on +discrete probability distributions represented as double arrays +
        • KMeansClusterer: uses the k-means algorithm to cluster +points in d-dimensional space into k clusters +
        • MapBinaryHeap: a binary heap implementation that permits +efficient element access and update operations +
        • RandomLocationTransformer: a class that randomly assigns +2D coordinates to items (default initializer for iterative Layouts) +
        • SettableTransformer: an extension of Transformer +that allows mutation of the transformation +
        + + + diff --git a/third-party/openflowj/LICENSE b/third-party/openflowj/LICENSE new file mode 100644 index 0000000000..ee6da46abe --- /dev/null +++ b/third-party/openflowj/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior +University + +We are making the OpenFlow specification and associated documentation +(Software) available for public use and benefit with the expectation that +others will use, modify and enhance the Software and contribute those +enhancements back to the community. However, since we would like to make the +Software available for broadest use, with as few restrictions as possible +permission is hereby granted, free of charge, to any person obtaining a copy of +this Software to deal in the Software under the copyrights without restriction, +including without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +The name and trademarks of copyright holder(s) may NOT be used in advertising +or publicity pertaining to the Software or any derivatives without specific, +written prior permission. diff --git a/third-party/openflowj/Makefile b/third-party/openflowj/Makefile new file mode 100644 index 0000000000..b803071a3e --- /dev/null +++ b/third-party/openflowj/Makefile @@ -0,0 +1,19 @@ +# Because I am old and crotchety and my fingers can't stop from running +# `make` commands +all: + ant + +run: + ant run + +doc: + ant javadoc + +tests: + ant tests + +count: + @find . -name \*.java | xargs wc -l | sort -n + +clean: + ant clean diff --git a/third-party/openflowj/README b/third-party/openflowj/README new file mode 100644 index 0000000000..6fffebef0b --- /dev/null +++ b/third-party/openflowj/README @@ -0,0 +1,16 @@ +OpenFlow Java - v1.0.0 + +A Java implementation of low-level OpenFlow packet marshalling/unmarshalling +and IO operations. Implements v1.0 of the OpenFlow specification at +http://www.openflow.org. + + - David Erickson (daviderickson@cs.stanford.edu) + - Rob Sherwood (rob.sherwood@stanford.edu) + +Building requires Maven 2.x+ (http://maven.apache.org/). + +To build: + mvn package + +To build javadocs: + mvn javadoc:javadoc diff --git a/third-party/openflowj/eclipse_codestyle.xml b/third-party/openflowj/eclipse_codestyle.xml new file mode 100644 index 0000000000..6b661c671d --- /dev/null +++ b/third-party/openflowj/eclipse_codestyle.xml @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/third-party/openflowj/lib/commons-cli-1.2.jar b/third-party/openflowj/lib/commons-cli-1.2.jar new file mode 100644 index 0000000000..ce4b9fffe4 Binary files /dev/null and b/third-party/openflowj/lib/commons-cli-1.2.jar differ diff --git a/third-party/openflowj/lib/junit-4.8.1.jar b/third-party/openflowj/lib/junit-4.8.1.jar new file mode 100644 index 0000000000..524cd65ce5 Binary files /dev/null and b/third-party/openflowj/lib/junit-4.8.1.jar differ diff --git a/third-party/openflowj/pom.xml b/third-party/openflowj/pom.xml new file mode 100644 index 0000000000..4daddf1162 --- /dev/null +++ b/third-party/openflowj/pom.xml @@ -0,0 +1,137 @@ + + 4.0.0 + org.opendaylight.controller.thirdparty + org.openflow.openflowj + 1.0.2-SNAPSHOT + OpenFlow Java + A Java implemention of the OpenFlow v1.0 protocol + + + + org.opendaylight.controller + commons.thirdparty + 1.1.0-SNAPSHOT + ../commons/thirdparty + + + + + David Erickson + daviderickson@cs.stanford.edu + + + Rob Sherwood + rob.sherwood@stanford.edu + + + bundle + http://www.openflow.org + + + The OpenFlow License + http://www.openflowswitch.org/wp/legal/ + repo + + + + scm:git://gitosis.stanford.edu:openflowj.git + https://openflow.stanford.edu/fisheye/browse/OpenFlowJ + + + UTF-8 + + + + + release-sign-artifacts + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.1 + + + sign-artifacts + verify + + sign + + + + + forked-path + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.openflow.example;version="1.0.1"; + uses:="org.openflow.example.cli, + org.openflow.protocol, + org.openflow.io, + org.openflow.protocol.factory", + org.openflow.io;version="1.0.1"; + uses:="org.openflow.protocol, + org.openflow.protocol.factory", + org.openflow.protocol;version="1.0.1"; + uses:="org.openflow.protocol.statistics, + org.openflow.protocol, + org.openflow.protocol.factory", + org.openflow.protocol.action;version="1.0.1"; + uses:="org.openflow.protocol", + org.openflow.protocol.factory;version="1.0.1"; + uses:="org.openflow.protocol.statistics, + org.openflow.protocol, + org.openflow.protocol.action, + org.openflow.protocol.queue", + org.openflow.protocol.queue;version="1.0.2"; + uses:="org.openflow.protocol, + org.openflow.protocol.factory", + org.openflow.protocol.statistics;version="1.0.1"; + uses:="org.openflow.protocol, + org.openflow.protocol.factory", + org.openflow.util;version="1.0.1" + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + + junit + junit + 4.8.1 + test + + + diff --git a/third-party/openflowj/src/main/java/org/openflow/example/SelectListener.java b/third-party/openflowj/src/main/java/org/openflow/example/SelectListener.java new file mode 100644 index 0000000000..16fa109c82 --- /dev/null +++ b/third-party/openflowj/src/main/java/org/openflow/example/SelectListener.java @@ -0,0 +1,21 @@ +/** + * + */ +package org.openflow.example; + +import java.io.IOException; +import java.nio.channels.SelectionKey; + +/** + * @author Rob Sherwood (rob.sherwood@stanford.edu) + * + */ +public interface SelectListener { + /** + * Tell the select listener that an event took place on the passed object + * @param key the key used on the select + * @param arg some parameter passed by the caller when registering + * @throws IOException + */ + void handleEvent(SelectionKey key, Object arg) throws IOException; +} diff --git a/third-party/openflowj/src/main/java/org/openflow/example/SelectLoop.java b/third-party/openflowj/src/main/java/org/openflow/example/SelectLoop.java new file mode 100644 index 0000000000..b7927d876e --- /dev/null +++ b/third-party/openflowj/src/main/java/org/openflow/example/SelectLoop.java @@ -0,0 +1,156 @@ +package org.openflow.example; + +import java.io.IOException; +import java.nio.channels.CancelledKeyException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.SelectorProvider; +import java.util.Iterator; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +/*** + * Dirt simple SelectLoop for simple java controller + */ + + +public class SelectLoop { + protected SelectListener callback; + protected boolean dontStop; + protected Object registrationLock; + protected int registrationRequests = 0; + protected Queue registrationQueue; + protected Selector selector; + protected long timeout; + + public SelectLoop(SelectListener cb) throws IOException { + callback = cb; + dontStop = true; + selector = SelectorProvider.provider().openSelector(); + registrationLock = new Object(); + registrationQueue = new ConcurrentLinkedQueue(); + timeout = 0; + } + + /** + * Initializes this SelectLoop + * @param cb the callback to call when select returns + * @param timeout the timeout value in milliseconds that select will be + * called with + * @throws IOException + */ + public SelectLoop(SelectListener cb, long timeout) throws IOException { + callback = cb; + dontStop = true; + selector = SelectorProvider.provider().openSelector(); + registrationLock = new Object(); + registrationQueue = new ConcurrentLinkedQueue(); + this.timeout = timeout; + } + + public void register(SelectableChannel ch, int ops, Object arg) + throws ClosedChannelException { + registrationQueue.add(new Object[] {ch, ops, arg}); + } + + /** + * Registers the supplied SelectableChannel with this SelectLoop. Note this + * method blocks until registration proceeds. It is advised that + * SelectLoop is intialized with a timeout value when using this method. + * @param ch the channel + * @param ops interest ops + * @param arg argument that will be returned with the SelectListener + * @return + * @throws ClosedChannelException + */ + public synchronized SelectionKey registerBlocking(SelectableChannel ch, int ops, Object arg) + throws ClosedChannelException { + synchronized (registrationLock) { + registrationRequests++; + } + selector.wakeup(); + SelectionKey key = ch.register(selector, ops, arg); + synchronized (registrationLock) { + registrationRequests--; + registrationLock.notifyAll(); + } + return key; + } + + /**** + * Main top-level IO loop this dispatches all IO events and timer events + * together I believe this is fairly efficient + */ + public void doLoop() throws IOException { + int nEvents; + processRegistrationQueue(); + + while (dontStop) { + nEvents = selector.select(timeout); + if (nEvents > 0) { + for (Iterator i = selector.selectedKeys() + .iterator(); i.hasNext();) { + SelectionKey sk = i.next(); + i.remove(); + + if (!sk.isValid()) + continue; + + Object arg = sk.attachment(); + callback.handleEvent(sk, arg); + } + } + + if (this.registrationQueue.size() > 0) + processRegistrationQueue(); + + if (registrationRequests > 0) { + synchronized (registrationLock) { + while (registrationRequests > 0) { + try { + registrationLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } + } + + protected void processRegistrationQueue() { + // add any elements in queue + for (Iterator it = registrationQueue.iterator(); it.hasNext();) { + Object[] args = it.next(); + SelectableChannel ch = (SelectableChannel) args[0]; + try { + ch.register(selector, (Integer) args[1], args[2]); + } catch (CancelledKeyException cke) { + continue; + } catch (ClosedChannelException e) { + } + it.remove(); + } + } + + /** + * Force this select loop to return immediately and re-enter select, useful + * for example if a new item has been added to the select loop while it + * was already blocked. + */ + public void wakeup() { + if (selector != null) { + selector.wakeup(); + } + } + + /** + * Shuts down this select loop, may return before it has fully shutdown + */ + public void shutdown() { + this.dontStop = false; + wakeup(); + } +} diff --git a/third-party/openflowj/src/main/java/org/openflow/example/SimpleController.java b/third-party/openflowj/src/main/java/org/openflow/example/SimpleController.java new file mode 100644 index 0000000000..e18e2f5fca --- /dev/null +++ b/third-party/openflowj/src/main/java/org/openflow/example/SimpleController.java @@ -0,0 +1,321 @@ +/** + * + */ +package org.openflow.example; + +import java.io.IOException; +import java.net.InetAddress; +import java.nio.channels.SelectionKey; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.openflow.example.cli.Options; +import org.openflow.example.cli.ParseException; +import org.openflow.example.cli.SimpleCLI; +import org.openflow.io.OFMessageAsyncStream; +import org.openflow.protocol.OFEchoReply; +import org.openflow.protocol.OFFlowMod; +import org.openflow.protocol.OFMatch; +import org.openflow.protocol.OFMessage; +import org.openflow.protocol.OFPacketIn; +import org.openflow.protocol.OFPacketOut; +import org.openflow.protocol.OFPort; +import org.openflow.protocol.OFType; +import org.openflow.protocol.action.OFAction; +import org.openflow.protocol.action.OFActionOutput; +import org.openflow.protocol.factory.BasicFactory; +import org.openflow.util.LRULinkedHashMap; +import org.openflow.util.U16; + +/** + * @author Rob Sherwood (rob.sherwood@stanford.edu), David Erickson (daviderickson@cs.stanford.edu) + * + */ +public class SimpleController implements SelectListener { + protected ExecutorService es; + protected BasicFactory factory; + protected SelectLoop listenSelectLoop; + protected ServerSocketChannel listenSock; + protected List switchSelectLoops; + protected Map switchSockets; + protected Integer threadCount; + protected int port; + + protected class OFSwitch { + protected SocketChannel sock; + protected OFMessageAsyncStream stream; + protected Map macTable = + new LRULinkedHashMap(64001, 64000); + + public OFSwitch(SocketChannel sock, OFMessageAsyncStream stream) { + this.sock = sock; + this.stream = stream; + } + + public void handlePacketIn(OFPacketIn pi) { + // Build the Match + OFMatch match = new OFMatch(); + match.loadFromPacket(pi.getPacketData(), pi.getInPort()); + byte[] dlDst = match.getDataLayerDestination(); + Integer dlDstKey = Arrays.hashCode(dlDst); + byte[] dlSrc = match.getDataLayerSource(); + Integer dlSrcKey = Arrays.hashCode(dlSrc); + int bufferId = pi.getBufferId(); + + // if the src is not multicast, learn it + if ((dlSrc[0] & 0x1) == 0) { + if (!macTable.containsKey(dlSrcKey) || + !macTable.get(dlSrcKey).equals(pi.getInPort())) { + macTable.put(dlSrcKey, pi.getInPort()); + } + } + + Short outPort = null; + // if the destination is not multicast, look it up + if ((dlDst[0] & 0x1) == 0) { + outPort = macTable.get(dlDstKey); + } + + // push a flow mod if we know where the packet should be going + if (outPort != null) { + OFFlowMod fm = (OFFlowMod) factory.getMessage(OFType.FLOW_MOD); + fm.setBufferId(bufferId); + fm.setCommand((short) 0); + fm.setCookie(0); + fm.setFlags((short) 0); + fm.setHardTimeout((short) 0); + fm.setIdleTimeout((short) 5); + match.setInputPort(pi.getInPort()); + match.setWildcards(0); + fm.setMatch(match); + fm.setOutPort((short) OFPort.OFPP_NONE.getValue()); + fm.setPriority((short) 0); + OFActionOutput action = new OFActionOutput(); + action.setMaxLength((short) 0); + action.setPort(outPort); + List actions = new ArrayList(); + actions.add(action); + fm.setActions(actions); + fm.setLength(U16.t(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH)); + try { + stream.write(fm); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // Send a packet out + if (outPort == null || pi.getBufferId() == 0xffffffff) { + OFPacketOut po = new OFPacketOut(); + po.setBufferId(bufferId); + po.setInPort(pi.getInPort()); + + // set actions + OFActionOutput action = new OFActionOutput(); + action.setMaxLength((short) 0); + action.setPort((short) ((outPort == null) ? OFPort.OFPP_FLOOD + .getValue() : outPort)); + List actions = new ArrayList(); + actions.add(action); + po.setActions(actions); + po.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); + + // set data if needed + if (bufferId == 0xffffffff) { + byte[] packetData = pi.getPacketData(); + po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH + + po.getActionsLength() + packetData.length)); + po.setPacketData(packetData); + } else { + po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH + + po.getActionsLength())); + } + try { + stream.write(po); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public String toString() { + InetAddress remote = sock.socket().getInetAddress(); + return remote.getHostAddress() + ":" + sock.socket().getPort(); + } + + public OFMessageAsyncStream getStream() { + return stream; + } + } + + public SimpleController(int port) throws IOException{ + listenSock = ServerSocketChannel.open(); + listenSock.configureBlocking(false); + listenSock.socket().bind(new java.net.InetSocketAddress(port)); + listenSock.socket().setReuseAddress(true); + this.port = port; + switchSelectLoops = new ArrayList(); + switchSockets = new ConcurrentHashMap(); + threadCount = 1; + listenSelectLoop = new SelectLoop(this); + // register this connection for accepting + listenSelectLoop.register(listenSock, SelectionKey.OP_ACCEPT, listenSock); + + this.factory = new BasicFactory(); + } + + @Override + public void handleEvent(SelectionKey key, Object arg) throws IOException { + if (arg instanceof ServerSocketChannel) + handleListenEvent(key, (ServerSocketChannel)arg); + else + handleSwitchEvent(key, (SocketChannel) arg); + } + + protected void handleListenEvent(SelectionKey key, ServerSocketChannel ssc) + throws IOException { + SocketChannel sock = listenSock.accept(); + OFMessageAsyncStream stream = new OFMessageAsyncStream(sock, factory); + switchSockets.put(sock, new OFSwitch(sock, stream)); + System.err + .println("Got new connection from " + switchSockets.get(sock)); + List l = new ArrayList(); + l.add(factory.getMessage(OFType.HELLO)); + l.add(factory.getMessage(OFType.FEATURES_REQUEST)); + stream.write(l); + + int ops = SelectionKey.OP_READ; + if (stream.needsFlush()) + ops |= SelectionKey.OP_WRITE; + + // hash this switch into a thread + SelectLoop sl = switchSelectLoops.get(sock.hashCode() + % switchSelectLoops.size()); + sl.register(sock, ops, sock); + // force select to return and re-enter using the new set of keys + sl.wakeup(); + } + + protected void handleSwitchEvent(SelectionKey key, SocketChannel sock) { + OFSwitch sw = switchSockets.get(sock); + OFMessageAsyncStream stream = sw.getStream(); + try { + if (key.isReadable()) { + List msgs = stream.read(); + if (msgs == null) { + key.cancel(); + switchSockets.remove(sock); + return; + } + + for (OFMessage m : msgs) { + switch (m.getType()) { + case PACKET_IN: + sw.handlePacketIn((OFPacketIn) m); + break; + case HELLO: + System.err.println("GOT HELLO from " + sw); + break; + case ECHO_REQUEST: + OFEchoReply reply = (OFEchoReply) stream + .getMessageFactory().getMessage( + OFType.ECHO_REPLY); + reply.setXid(m.getXid()); + stream.write(reply); + break; + default: + System.err.println("Unhandled OF message: " + + m.getType() + " from " + + sock.socket().getInetAddress()); + } + } + } + if (key.isWritable()) { + stream.flush(); + } + + /** + * Only register for interest in R OR W, not both, causes stream + * deadlock after some period of time + */ + if (stream.needsFlush()) + key.interestOps(SelectionKey.OP_WRITE); + else + key.interestOps(SelectionKey.OP_READ); + } catch (IOException e) { + // if we have an exception, disconnect the switch + key.cancel(); + switchSockets.remove(sock); + } + } + + public void run() throws IOException{ + System.err.println("Starting " + this.getClass().getCanonicalName() + + " on port " + this.port + " with " + this.threadCount + " threads"); + // Static number of threads equal to processor cores + es = Executors.newFixedThreadPool(threadCount); + + // Launch one select loop per threadCount and start running + for (int i = 0; i < threadCount; ++i) { + final SelectLoop sl = new SelectLoop(this); + switchSelectLoops.add(sl); + es.execute(new Runnable() { + @Override + public void run() { + try { + sl.doLoop(); + } catch (IOException e) { + e.printStackTrace(); + } + }} + ); + } + + // Start the listen loop + listenSelectLoop.doLoop(); + } + + public static void main(String [] args) throws IOException { + SimpleCLI cmd = parseArgs(args); + int port = Integer.valueOf(cmd.getOptionValue("p")); + SimpleController sc = new SimpleController(port); + sc.threadCount = Integer.valueOf(cmd.getOptionValue("t")); + sc.run(); + } + + public static SimpleCLI parseArgs(String[] args) { + Options options = new Options(); + options.addOption("h", "help", "print help"); + // unused? + // options.addOption("n", true, "the number of packets to send"); + options.addOption("p", "port", 6633, "the port to listen on"); + options.addOption("t", "threads", 1, "the number of threads to run"); + try { + SimpleCLI cmd = SimpleCLI.parse(options, args); + if (cmd.hasOption("h")) { + printUsage(options); + System.exit(0); + } + return cmd; + } catch (ParseException e) { + System.err.println(e); + printUsage(options); + } + + System.exit(-1); + return null; + } + + public static void printUsage(Options options) { + SimpleCLI.printHelp("Usage: " + + SimpleController.class.getCanonicalName() + " [options]", + options); + } +} diff --git a/third-party/openflowj/src/main/java/org/openflow/example/cli/Option.java b/third-party/openflowj/src/main/java/org/openflow/example/cli/Option.java new file mode 100644 index 0000000000..acf8446d4b --- /dev/null +++ b/third-party/openflowj/src/main/java/org/openflow/example/cli/Option.java @@ -0,0 +1,40 @@ +package org.openflow.example.cli; + +public class Option { + String shortOpt; + String longOpt; + Object defaultVal; + String val; // current value of this option, string form + boolean specified; // was this option found in the cmdline? + String comment; + + /** + * Option information storrage + * + * @param shortOpt + * Short name for the option, e.g., "-p" + * @param longOpt + * Long name for option, e.g., "--port" + * @param defaultVal + * default value: "6633" or null if no default value + * @param comment + * String to print to explain this option, e.g., a help message + */ + public Option(String shortOpt, String longOpt, Object defaultVal, + String comment) { + super(); + this.shortOpt = shortOpt; + this.longOpt = longOpt; + this.defaultVal = defaultVal; + this.comment = comment; + this.specified = false; + } + + public Option(String shortOpt, String longOpt, String comment) { + this(shortOpt, longOpt, null, comment); + } + + public boolean needsArg() { + return this.defaultVal != null; + } +} diff --git a/third-party/openflowj/src/main/java/org/openflow/example/cli/Options.java b/third-party/openflowj/src/main/java/org/openflow/example/cli/Options.java new file mode 100644 index 0000000000..7f55b50bc6 --- /dev/null +++ b/third-party/openflowj/src/main/java/org/openflow/example/cli/Options.java @@ -0,0 +1,69 @@ +package org.openflow.example.cli; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Very basic CLI options listing + * + * @author Rob Sherwood (rob.sherwood@stanford.edu) + * + */ + +public class Options { + Map shortOptionsMap; + Map longOptionsMap; + + public Options() { + this.shortOptionsMap = new HashMap(); + this.longOptionsMap = new HashMap(); + } + + public static Options make(Option opts[]) { + Options options = new Options(); + for (int i = 0; i < opts.length; i++) + options.addOption(opts[i]); + return options; + } + + private void addOption(Option option) { + if (option.shortOpt != null) + this.shortOptionsMap.put(option.shortOpt, option); + if (option.longOpt != null) + this.longOptionsMap.put(option.longOpt, option); + } + + protected void addOption(String shortName, String longName, Object o, + String comment) { + Option option = new Option(shortName, longName, o, comment); + addOption(option); + } + + public void addOption(String shortName, String longName, boolean b, + String comment) { + this.addOption(shortName, longName, Boolean.valueOf(b), comment); + } + + public void addOption(String shortName, String longName, int i, + String comment) { + this.addOption(shortName, longName, Integer.valueOf(i), comment); + } + + public Option getOption(String shortName) { + return this.shortOptionsMap.get(shortName); + } + + public Option getOptionByLongName(String longName) { + return this.longOptionsMap.get(longName); + } + + public Collection