Merge "Introducing ShardManager"
authorTony Tkacik <ttkacik@cisco.com>
Fri, 20 Jun 2014 12:13:07 +0000 (12:13 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 20 Jun 2014 12:13:07 +0000 (12:13 +0000)
148 files changed:
opendaylight/commons/opendaylight/pom.xml
opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java
opendaylight/distribution/opendaylight/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicator.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/MediaTypesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestGetOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.java
opendaylight/md-sal/sal-rest-connector/src/test/resources/modules/nested-module.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/pom.xml
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/DocProvider.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/api/ApiDocService.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocServiceImpl.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/BaseYangSwaggerGenerator.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ModelGenerator.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/jaxrs/ApiDocApplication.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/jaxrs/JaxbContextResolver.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/model/builder/OperationBuilder.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/mountpoints/MountPointSwagger.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Api.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ApiDeclaration.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Operation.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Parameter.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Resource.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ResourceList.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ResponseMessage.java
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/animated-overlay.gif [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_222222_256x240.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_228ef1_256x240.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ef8c08_256x240.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ffd27a_256x240.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ffffff_256x240.png [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/jquery-ui-1.10.4.custom.css [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/jquery-ui-1.10.4.custom.min.css [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/logo_small.png
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/index.html
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/jquery-ui-1.11.0.min.js [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/odl/list_mounts.js [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/odl/swagger.js [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/DocGenTestHelper.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/DocGeneratorTest.java [deleted file]
opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/MountPointSwaggerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_short.yang [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectNameAttributeReadingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectNameAttributeWritingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpcElementResolved.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/ValidateTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java
opendaylight/netconf/netconf-api/pom.xml
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfDocumentedException.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/xml/XmlNetconfConstants.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java with 84% similarity]
opendaylight/netconf/netconf-api/src/test/java/org/opendaylight/controller/netconf/api/NetconfDocumentedExceptionTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiator.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SubtreeFilter.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/SubtreeFilterTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/getConfig_reply_unfiltered.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/logback-test.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/post-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/pre-filter.xml [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/request.xml [new file with mode: 0644]
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/exi/NetconfStartExiMessage.java
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/netty/SSHTest.java
opendaylight/netconf/netconf-util/pom.xml
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessage.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/northbound/swagger-ui/pom.xml [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png [new file with mode: 0644]
opendaylight/northbound/swagger-ui/src/main/resources/index.html [new file with mode: 0644]
opendaylight/sal/connection/implementation/src/main/java/org/opendaylight/controller/sal/connection/implementation/internal/ConnectionService.java
pom.xml

index 92e4ee0b481a7bd58c1ef0143fa4a97a0095a8e9..3f1fa38ebd8631d4e0c4b1917088a91edb637c7c 100644 (file)
@@ -20,8 +20,8 @@
     <appauth.version>0.4.2-SNAPSHOT</appauth.version>
     <archetype-app-northbound>0.0.1-SNAPSHOT</archetype-app-northbound>
     <aries.util.version>1.1.0</aries.util.version>
-    <!-- Controller Modules Versions -->
     <arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
+    <!-- Controller Modules Versions -->
     <arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
     <asm.version>4.1</asm.version>
     <!-- Plugin Versions -->
     <clustering.stub.version>0.4.2-SNAPSHOT</clustering.stub.version>
     <clustering.test.version>0.4.2-SNAPSHOT</clustering.test.version>
     <commmons.northbound.version>0.4.2-SNAPSHOT</commmons.northbound.version>
-    <commons.checkstyle.version>0.0.3-SNAPSHOT</commons.checkstyle.version>
     <!-- Third Party Versions -->
+    <commons.catalina>7.0.32.v201211201336</commons.catalina>
+    <commons.catalina.ha>7.0.32.v201211201952</commons.catalina.ha>
+    <commons.catalina.tribes>7.0.32.v201211201952</commons.catalina.tribes>
+    <commons.checkstyle.version>0.0.3-SNAPSHOT</commons.checkstyle.version>
     <commons.codec.version>1.7</commons.codec.version>
+    <commons.coyote>7.0.32.v201211201952</commons.coyote>
+    <commons.el>7.0.32.v201211081135</commons.el>
     <commons.fileupload.version>1.2.2</commons.fileupload.version>
     <commons.httpclient.version>0.1.2-SNAPSHOT</commons.httpclient.version>
     <commons.io.version>2.4</commons.io.version>
+    <commons.jasper>7.0.32.v201211201952</commons.jasper>
+    <commons.juli.version>7.0.32.v201211081135</commons.juli.version>
     <commons.lang.version>3.1</commons.lang.version>
     <commons.logback_settings.version>0.0.2-SNAPSHOT</commons.logback_settings.version>
     <commons.net.version>3.0.1</commons.net.version>
@@ -49,6 +56,8 @@
     <commons.opendaylight.concepts.version>0.5.2-SNAPSHOT</commons.opendaylight.concepts.version>
     <commons.opendaylight.version>1.4.2-SNAPSHOT</commons.opendaylight.version>
     <commons.parent.version>1.0.2-SNAPSHOT</commons.parent.version>
+    <commons.tomcat.api>7.0.32.v201211081135</commons.tomcat.api>
+    <commons.tomcat.util>7.0.32.v201211201952</commons.tomcat.util>
     <compiler.version>2.3.2</compiler.version>
     <concepts.version>0.5.2-SNAPSHOT</concepts.version>
     <config.version>0.2.5-SNAPSHOT</config.version>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.catalina</artifactId>
-        <version>7.0.32.v201211201336</version>
+        <version>${commons.catalina}</version>
       </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.catalina.ha</artifactId>
-        <version>7.0.32.v201211201952</version>
+        <version>${commons.catalina.ha}</version>
       </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.catalina.tribes</artifactId>
-        <version>7.0.32.v201211201952</version>
+        <version>${commons.catalina.tribes}</version>
       </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.coyote</artifactId>
-        <version>7.0.32.v201211201952</version>
+        <version>${commons.coyote}</version>
       </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.el</artifactId>
-        <version>7.0.32.v201211081135</version>
+        <version>${commons.el}</version>
       </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.jasper</artifactId>
-        <version>7.0.32.v201211201952</version>
+        <version>${commons.jasper}</version>
       </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.juli.extras</artifactId>
-        <version>7.0.32.v201211081135</version>
+        <version>${commons.juli.version}</version>
       </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.tomcat.api</artifactId>
-        <version>7.0.32.v201211081135</version>
+        <version>${commons.tomcat.api}</version>
       </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>org.apache.tomcat.util</artifactId>
-        <version>7.0.32.v201211201952</version>
+        <version>${commons.tomcat.util}</version>
       </dependency>
       <dependency>
         <groupId>org.aopalliance</groupId>
index ebc56928a23856a158b4247d98c2720af9f98ac6..d76c094851123394a2c967a0b9aa4aaf020be90d 100644 (file)
@@ -261,7 +261,7 @@ public class ConnectionManager implements IConnectionManager,
             Map<ConnectionConstants, String> params) {
         if (connectionService == null)
             return null;
-        Node node = connectionService.connect(connectionIdentifier, params);
+        Node node = connectionService.connect(type, connectionIdentifier, params);
         AbstractScheme scheme = schemes.get(activeScheme);
         if (scheme != null && node != null)
             scheme.addNode(node);
index 3916e05496ab2a40fc34e2adb71fd53839172ceb..7160acba8173fdf2e4981f84e44d877c8b830ce5 100644 (file)
         </plugins>
       </build>
     </profile>
+    <profile>
+      <id>docs</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>swagger-ui</artifactId>
+          <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+      </dependencies>
+    </profile>
   </profiles>
 </project>
index e5a9d3e5db87280717058126d6335114d9c2d2d5..ba7377e8ff3dd1b8fd6c69df70e70435d39cb2a9 100644 (file)
@@ -163,6 +163,7 @@ public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, Sa
 
     @Override
     public void onFlowRemoved(final FlowRemoved notification) {
+        // notified upon remove flow rpc successfully invoked
         if (notification == null) {
             return;
         }
@@ -190,7 +191,25 @@ public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, Sa
 
     @Override
     public void onSwitchFlowRemoved(final SwitchFlowRemoved notification) {
-        // FIXME: unfinished?
+        // notified upon remove flow message from device arrives
+        if (notification == null) {
+            return;
+        }
+
+        final NodeRef node = notification.getNode();
+        if (node == null) {
+            LOG.debug("Notification {} has not node, ignoring it", notification);
+            return;
+        }
+
+        Node adNode;
+        try {
+            adNode = NodeMapping.toADNode(notification.getNode());
+        } catch (ConstructionException e) {
+            LOG.warn("Failed to construct AD node for {}, ignoring notification", node, e);
+            return;
+        }
+        flowProgrammerPublisher.flowRemoved(adNode, ToSalConversionsUtils.toFlow(notification, adNode));
     }
 
     @Override
index ba86ad99fb9bcde573c3cb4404d12d444ab697ba..f5701bfaf23419c9c2beaed1bde59f2037095c3c 100644 (file)
@@ -124,6 +124,14 @@ public final class NodeMapping {
         return nodeConnectorId.getValue();
     }
 
+    public static NodeId toAdNodeId(final NodeConnectorId nodeConnectorId) {
+        NodeId nodeId = null;
+        if (nodeConnectorId != null) {
+            nodeId = new NodeId(nodeConnectorId.getValue().replaceFirst(":[0-9]+$", ""));
+        }
+        return nodeId;
+    }
+
     public static NodeConnectorId toControllerNodeConnectorId(final NodeId node) {
         return new NodeConnectorId(node.getValue() + ":" + 4294967293L);
     }
index da3477ee45329e57d6174c01b9d53de76b098c39..b64f17a77028ff018df7691d4f0498027356d4a8 100644 (file)
@@ -55,6 +55,7 @@ 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
@@ -94,8 +95,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.GenericFlowAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
@@ -114,18 +118,53 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.net.InetAddresses;
 
 public class ToSalConversionsUtils {
 
+    private static final Logger LOG = LoggerFactory.getLogger(ToSalConversionsUtils.class);
+
     private ToSalConversionsUtils() {
 
     }
 
     public static Flow toFlow(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source, Node node) {
         final Flow target = new Flow();
+        genericFlowToAdFlow(source, target);
+        
+        target.setMatch(toMatch(source.getMatch()));
+
+        List<Action> actions = getAction(source);
+        if (actions != null) {
+            target.setActions(actionFrom(actions, node));
+        }
+
+        return target;
+    }
+    
+    /**
+     * @param source notification, missing instructions
+     * @param node corresponding node where the flow change occured
+     * @return ad-sal node, build from given data
+     */
+    public static Flow toFlow(SwitchFlowRemoved source, Node node) {
+        final Flow target = new Flow();
+        genericFlowToAdFlow(source, target);
+
+        target.setMatch(toMatch(source.getMatch()));
+
+        return target;
+    }
 
+    /**
+     * @param source
+     * @param target
+     */
+    private static void genericFlowToAdFlow(GenericFlowAttributes source,
+            final Flow target) {
         Integer hardTimeout = source.getHardTimeout();
         if (hardTimeout != null) {
             target.setHardTimeout(hardTimeout.shortValue());
@@ -140,18 +179,9 @@ public class ToSalConversionsUtils {
         if (priority != null) {
             target.setPriority(priority.shortValue());
         }
-
-        target.setMatch(toMatch(source.getMatch()));
-
-        List<Action> actions = getAction(source);
-        if (actions != null) {
-            target.setActions(actionFrom(actions, node));
-        }
-
         target.setId(source.getCookie().getValue().longValue());
-        return target;
     }
-
+    
     public static List<Action> getAction(
             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source) {
         if (source.getInstructions() != null) {
@@ -356,7 +386,7 @@ public class ToSalConversionsUtils {
         return nodeConnector;
     }
 
-    public static Match toMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match source) {
+    public static Match toMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match source) {
         Match target = new Match();
         if (source != null) {
             fillFrom(target, source.getVlanMatch());
@@ -364,11 +394,30 @@ public class ToSalConversionsUtils {
             fillFrom(target, source.getLayer3Match());
             fillFrom(target, source.getLayer4Match());
             fillFrom(target, source.getIpMatch());
+            fillFrom(target, source.getInPort());
         }
 
         return target;
     }
 
+    /**
+     * @param target
+     * @param inPort
+     */
+    private static void fillFrom(Match target, NodeConnectorId inPort) {
+        if (inPort != null) {
+            String inPortValue = inPort.getValue();
+            if (inPortValue != null) {
+                try {
+                    target.setField(MatchType.IN_PORT, NodeMapping.toADNodeConnector(inPort,
+                            NodeMapping.toAdNodeId(inPort)));
+                } catch (ConstructionException e) {
+                    LOG.warn("nodeConnector construction failed", e);
+                }
+            }
+        }
+    }
+
     private static void fillFrom(Match target, VlanMatch vlanMatch) {
         if (vlanMatch != null) {
             VlanId vlanId = vlanMatch.getVlanId();
index 041924af336c7b1e20647eb64526cbdf961e9329..b418e6dc25879050d7e9525e671cf080c0444401 100644 (file)
@@ -11,6 +11,7 @@ import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.sal.compatibility.NodeMapping;
 import org.opendaylight.controller.sal.core.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 
 /**
@@ -55,4 +56,19 @@ public class NodeMappingTest {
         }
     }
 
+    /**
+     * Test method for
+     * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toAdNodeId(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId)}
+     * .
+     */
+    @Test
+    public void testToAdNodeId() {
+        NodeId observed;
+        observed = NodeMapping.toAdNodeId(null);
+        Assert.assertNull(observed);
+
+        observed = NodeMapping.toAdNodeId(new NodeConnectorId("MD_SAL|openflow:5:2"));
+        Assert.assertEquals("MD_SAL|openflow:5", observed.getValue());
+    }
+
 }
index e78f2b32df0cbc338bad5b28ac1d5063084b9b96..4da727f5c24e56e37c4e11acd6150d9afded1cd8 100644 (file)
@@ -10,17 +10,20 @@ package org.opendaylight.controller.sal.connect.netconf.listener;
 import java.util.ArrayDeque;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Queue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.NetconfClientSession;
 import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
 import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.controller.sal.common.util.Rpcs;
@@ -35,6 +38,8 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -45,12 +50,9 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfDeviceCommunicator.class);
 
-    private static final RpcResult<NetconfMessage> FAILED_RPC_RESULT = new FailedRpcResult<>(RpcErrors.getRpcError(
-            null, null, null, RpcError.ErrorSeverity.ERROR, "Netconf session disconnected",
-            RpcError.ErrorType.PROTOCOL, null));
-
     private final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice;
     private final RemoteDeviceId id;
+    private final Lock sessionLock = new ReentrantLock();
 
     public NetconfDeviceCommunicator(final RemoteDeviceId id,
             final RemoteDevice<NetconfSessionCapabilities, NetconfMessage> remoteDevice) {
@@ -62,14 +64,21 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
     private NetconfClientSession session;
 
     @Override
-    public synchronized void onSessionUp(final NetconfClientSession session) {
-        logger.debug("{}: Session established", id);
-        this.session = session;
+    public void onSessionUp(final NetconfClientSession session) {
+        sessionLock.lock();
+        try {
+            logger.debug("{}: Session established", id);
+            this.session = session;
 
-        final NetconfSessionCapabilities netconfSessionCapabilities = NetconfSessionCapabilities.fromNetconfSession(session);
-        logger.trace("{}: Session advertised capabilities: {}", id, netconfSessionCapabilities);
+            final NetconfSessionCapabilities netconfSessionCapabilities =
+                                             NetconfSessionCapabilities.fromNetconfSession(session);
+            logger.trace("{}: Session advertised capabilities: {}", id, netconfSessionCapabilities);
 
-        remoteDevice.onRemoteSessionUp(netconfSessionCapabilities, this);
+            remoteDevice.onRemoteSessionUp(netconfSessionCapabilities, this);
+        }
+        finally {
+            sessionLock.unlock();
+        }
     }
 
     public void initializeRemoteConnection(final NetconfClientDispatcher dispatch,
@@ -77,37 +86,75 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
         dispatch.createReconnectingClient(config);
     }
 
-    private synchronized void tearDown(final Exception e) {
-        remoteDevice.onRemoteSessionDown();
-        session = null;
+    private void tearDown( String reason ) {
+        List<UncancellableFuture<RpcResult<NetconfMessage>>> futuresToCancel = Lists.newArrayList();
+        sessionLock.lock();
+        try {
+            if( session != null ) {
+                session = null;
+
+                /*
+                 * Walk all requests, check if they have been executing
+                 * or cancelled and remove them from the queue.
+                 */
+                final Iterator<Request> it = requests.iterator();
+                while (it.hasNext()) {
+                    final Request r = it.next();
+                    if (r.future.isUncancellable()) {
+                        futuresToCancel.add( r.future );
+                        it.remove();
+                    } else if (r.future.isCancelled()) {
+                        // This just does some house-cleaning
+                        it.remove();
+                    }
+                }
 
-        /*
-         * Walk all requests, check if they have been executing
-         * or cancelled and remove them from the queue.
-         */
-        final Iterator<Request> it = requests.iterator();
-        while (it.hasNext()) {
-            final Request r = it.next();
-            if (r.future.isUncancellable()) {
-                r.future.setException(e);
-                it.remove();
-            } else if (r.future.isCancelled()) {
-                // This just does some house-cleaning
-                it.remove();
+                remoteDevice.onRemoteSessionDown();
+            }
+        }
+        finally {
+            sessionLock.unlock();
+        }
+
+        // Notify pending request futures outside of the sessionLock to avoid unnecessarily
+        // blocking the caller.
+        for( UncancellableFuture<RpcResult<NetconfMessage>> future: futuresToCancel ) {
+            if( Strings.isNullOrEmpty( reason ) ) {
+                future.set( createSessionDownRpcResult() );
+            } else {
+                future.set( createErrorRpcResult( RpcError.ErrorType.TRANSPORT, reason ) );
             }
         }
     }
 
+    private RpcResult<NetconfMessage> createSessionDownRpcResult()
+    {
+        return createErrorRpcResult( RpcError.ErrorType.TRANSPORT,
+                             String.format( "The netconf session to %1$s is disconnected", id.getName() ) );
+    }
+
+    private RpcResult<NetconfMessage> createErrorRpcResult( RpcError.ErrorType errorType, String message )
+    {
+        return new FailedRpcResult<NetconfMessage>( RpcErrors.getRpcError( null,
+                NetconfDocumentedException.ErrorTag.operation_failed.getTagValue(),
+                null, RpcError.ErrorSeverity.ERROR, message, errorType, null ) );
+    }
+
     @Override
     public void onSessionDown(final NetconfClientSession session, final Exception e) {
         logger.warn("{}: Session went down", id, e);
-        tearDown(e);
+        tearDown( null );
     }
 
     @Override
     public void onSessionTerminated(final NetconfClientSession session, final NetconfTerminationReason reason) {
         logger.warn("{}: Session terminated {}", id, reason);
-        tearDown(new RuntimeException(reason.getErrorMessage()));
+        tearDown( reason.getErrorMessage() );
+    }
+
+    @Override
+    public void close() {
+        tearDown( String.format( "The netconf session to %1$s has been closed", id.getName() ) );
     }
 
     @Override
@@ -123,73 +170,109 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
         }
     }
 
-    private synchronized void processMessage(final NetconfMessage message) {
-        final Request r = requests.peek();
-        if (r.future.isUncancellable()) {
-            requests.poll();
+    private void processMessage(final NetconfMessage message) {
+        Request request = null;
+        sessionLock.lock();
+        try {
+            request = requests.peek();
+            if (request.future.isUncancellable()) {
+                requests.poll();
+            }
+            else {
+                request = null;
+                logger.warn("{}: Ignoring unsolicited message {}", id, msgToS(message));
+            }
+        }
+        finally {
+            sessionLock.unlock();
+        }
+
+        if( request != null ) {
 
             logger.debug("{}: Message received {}", id, message);
 
             if(logger.isTraceEnabled()) {
-                logger.trace("{}: Matched request: {} to response: {}", id, msgToS(r.request), msgToS(message));
+                logger.trace( "{}: Matched request: {} to response: {}", id,
+                              msgToS( request.request ), msgToS( message ) );
             }
 
             try {
-                NetconfMessageTransformUtil.checkValidReply(r.request, message);
-            } catch (final IllegalStateException e) {
-                logger.warn("{}: Invalid request-reply match, reply message contains different message-id, request: {}, response: {}", id,
-                        msgToS(r.request), msgToS(message), e);
-                r.future.setException(e);
+                NetconfMessageTransformUtil.checkValidReply( request.request, message );
+            }
+            catch (final NetconfDocumentedException e) {
+                logger.warn( "{}: Invalid request-reply match, reply message contains different message-id, request: {}, response: {}",
+                             id, msgToS( request.request ), msgToS( message ), e );
+
+                request.future.set( new FailedRpcResult<NetconfMessage>(
+                                                           NetconfMessageTransformUtil.toRpcError( e ) ) );
                 return;
             }
 
             try {
                 NetconfMessageTransformUtil.checkSuccessReply(message);
-            } catch (NetconfDocumentedException | IllegalStateException e) {
-                logger.warn("{}: Error reply from remote device, request: {}, response: {}", id,
-                        msgToS(r.request), msgToS(message), e);
-                r.future.setException(e);
+            }
+            catch( NetconfDocumentedException e ) {
+                logger.warn( "{}: Error reply from remote device, request: {}, response: {}", id,
+                             msgToS( request.request ), msgToS( message ), e );
+
+                request.future.set( new FailedRpcResult<NetconfMessage>(
+                                                          NetconfMessageTransformUtil.toRpcError( e ) ) );
                 return;
             }
 
-            r.future.set(Rpcs.getRpcResult(true, message, Collections.<RpcError>emptySet()));
-        } else {
-            logger.warn("{}: Ignoring unsolicited message {}", id, msgToS(message));
+            request.future.set(Rpcs.getRpcResult( true, message, Collections.<RpcError>emptySet() ) );
         }
     }
 
-    @Override
-    public void close() {
-        tearDown(new RuntimeException("Closed"));
-    }
-
     private static String msgToS(final NetconfMessage msg) {
         return XmlUtil.toString(msg.getDocument());
     }
 
     @Override
-    public synchronized ListenableFuture<RpcResult<NetconfMessage>> sendRequest(final NetconfMessage message, final QName rpc) {
+    public ListenableFuture<RpcResult<NetconfMessage>> sendRequest(
+                                               final NetconfMessage message, final QName rpc) {
+        sessionLock.lock();
+        try {
+            return sendRequestWithLock( message, rpc );
+        }
+        finally {
+            sessionLock.unlock();
+        }
+    }
+
+    private ListenableFuture<RpcResult<NetconfMessage>> sendRequestWithLock(
+                                               final NetconfMessage message, final QName rpc) {
         if(logger.isTraceEnabled()) {
             logger.trace("{}: Sending message {}", id, msgToS(message));
         }
 
         if (session == null) {
             logger.warn("{}: Session is disconnected, failing RPC request {}", id, message);
-            return Futures.immediateFuture(FAILED_RPC_RESULT);
+            return Futures.immediateFuture( createSessionDownRpcResult() );
         }
 
-        final Request req = new Request(new UncancellableFuture<RpcResult<NetconfMessage>>(true), message, rpc);
+        final Request req = new Request( new UncancellableFuture<RpcResult<NetconfMessage>>(true),
+                                         message );
         requests.add(req);
 
         session.sendMessage(req.request).addListener(new FutureListener<Void>() {
             @Override
             public void operationComplete(final Future<Void> future) throws Exception {
-                if (!future.isSuccess()) {
+                if( !future.isSuccess() ) {
                     // We expect that a session down will occur at this point
-                    logger.debug("{}: Failed to send request {}", id, XmlUtil.toString(req.request.getDocument()), future.cause());
-                    req.future.setException(future.cause());
-                } else {
-                    logger.trace("{}: Finished sending request {}", id, req.request);
+                    logger.debug( "{}: Failed to send request {}", id,
+                                  XmlUtil.toString(req.request.getDocument()), future.cause() );
+
+                    if( future.cause() != null ) {
+                        req.future.set( createErrorRpcResult( RpcError.ErrorType.TRANSPORT,
+                                                              future.cause().getLocalizedMessage() ) );
+                    } else {
+                        req.future.set( createSessionDownRpcResult() ); // assume session is down
+                    }
+                    req.future.setException( future.cause() );
+                }
+                else {
+                    logger.trace( "Finished sending request {}", req.request );
                 }
             }
         });
@@ -215,12 +298,11 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
     private static final class Request {
         final UncancellableFuture<RpcResult<NetconfMessage>> future;
         final NetconfMessage request;
-        final QName rpc;
 
-        private Request(final UncancellableFuture<RpcResult<NetconfMessage>> future, final NetconfMessage request, final QName rpc) {
+        private Request(final UncancellableFuture<RpcResult<NetconfMessage>> future,
+                        final NetconfMessage request) {
             this.future = future;
             this.request = request;
-            this.rpc = rpc;
         }
     }
 }
index 1284d6d1ce3cd67d8b9355622873db46a46754b5..08a5822d366d16fa5d078e17ae8af2065cdba30e 100644 (file)
@@ -12,14 +12,17 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import javax.annotation.Nullable;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.controller.sal.common.util.RpcErrors;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.Node;
@@ -36,6 +39,7 @@ import org.w3c.dom.Element;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
@@ -99,20 +103,68 @@ public class NetconfMessageTransformUtil {
         return new CompositeNodeTOImpl(argument.getNodeType(), null, list);
     }
 
-    public static void checkValidReply(final NetconfMessage input, final NetconfMessage output) {
+    public static void checkValidReply(final NetconfMessage input, final NetconfMessage output)
+        throws NetconfDocumentedException {
         final String inputMsgId = input.getDocument().getDocumentElement().getAttribute("message-id");
         final String outputMsgId = output.getDocument().getDocumentElement().getAttribute("message-id");
 
         if(inputMsgId.equals(outputMsgId) == false) {
-            final String requestXml = XmlUtil.toString(input.getDocument());
-            final String responseXml = XmlUtil.toString(output.getDocument());
-            throw new IllegalStateException(String.format("Rpc request and reply message IDs must be same. Request: %s, response: %s", requestXml, responseXml));
+            Map<String,String> errorInfo = ImmutableMap.<String,String>builder()
+                .put( "actual-message-id", outputMsgId )
+                .put( "expected-message-id", inputMsgId )
+                .build();
+
+            throw new NetconfDocumentedException( "Response message contained unknown \"message-id\"",
+                    null, NetconfDocumentedException.ErrorType.protocol,
+                    NetconfDocumentedException.ErrorTag.bad_attribute,
+                    NetconfDocumentedException.ErrorSeverity.error, errorInfo );
         }
     }
 
     public static void checkSuccessReply(final NetconfMessage output) throws NetconfDocumentedException {
         if(NetconfMessageUtil.isErrorMessage(output)) {
-            throw new IllegalStateException(String.format("Response contains error: %s", XmlUtil.toString(output.getDocument())));
+            throw NetconfDocumentedException.fromXMLDocument( output.getDocument() );
+        }
+    }
+
+    public static RpcError toRpcError( NetconfDocumentedException ex )
+    {
+        StringBuilder infoBuilder = new StringBuilder();
+        Map<String, String> errorInfo = ex.getErrorInfo();
+        if( errorInfo != null )
+        {
+            for( Entry<String,String> e: errorInfo.entrySet() ) {
+                infoBuilder.append( '<' ).append( e.getKey() ).append( '>' ).append( e.getValue() )
+                           .append( "</" ).append( e.getKey() ).append( '>' );
+
+            }
+        }
+
+        return RpcErrors.getRpcError( null, ex.getErrorTag().getTagValue(), infoBuilder.toString(),
+                                      toRpcErrorSeverity( ex.getErrorSeverity() ), ex.getLocalizedMessage(),
+                                      toRpcErrorType( ex.getErrorType() ), ex.getCause() );
+    }
+
+    private static ErrorSeverity toRpcErrorSeverity( NetconfDocumentedException.ErrorSeverity severity ) {
+        switch( severity ) {
+            case warning:
+                return RpcError.ErrorSeverity.WARNING;
+            default:
+                return RpcError.ErrorSeverity.ERROR;
+        }
+    }
+
+    private static RpcError.ErrorType toRpcErrorType( NetconfDocumentedException.ErrorType type )
+    {
+        switch( type ) {
+            case protocol:
+                return RpcError.ErrorType.PROTOCOL;
+            case rpc:
+                return RpcError.ErrorType.RPC;
+            case transport:
+                return RpcError.ErrorType.TRANSPORT;
+            default:
+                return RpcError.ErrorType.APPLICATION;
         }
     }
 
index 5ac32b5b3c918bd83d89764f940654641bfebbdd..c1b9f7b47ba8b8009b620655a729703e1809346f 100644 (file)
@@ -26,7 +26,7 @@ import java.util.concurrent.Executors;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.connect.api.MessageTransformer;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java
new file mode 100644 (file)
index 0000000..391bf9c
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.connect.netconf.listener;
+
+import io.netty.channel.ChannelFuture;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
+
+import java.io.ByteArrayInputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_REPLY_KEY;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
+import org.opendaylight.controller.netconf.client.NetconfClientSession;
+import org.opendaylight.controller.sal.connect.api.RemoteDevice;
+import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class NetconfDeviceCommunicatorTest {
+
+    @Mock
+    NetconfClientSession mockSession;
+
+    @Mock
+    RemoteDevice<NetconfSessionCapabilities, NetconfMessage> mockDevice;
+
+    NetconfDeviceCommunicator communicator;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks( this );
+
+        communicator = new NetconfDeviceCommunicator( new RemoteDeviceId( "test" ), mockDevice );
+    }
+
+    @SuppressWarnings("unchecked")
+    void setupSession()
+    {
+        doReturn( Collections.<String>emptySet() ).when( mockSession ).getServerCapabilities();
+        doNothing().when( mockDevice ).onRemoteSessionUp( any( NetconfSessionCapabilities.class ),
+                                                          any( RemoteDeviceCommunicator.class ) );
+        communicator.onSessionUp( mockSession );
+    }
+
+    private ListenableFuture<RpcResult<NetconfMessage>> sendRequest() throws Exception {
+        return sendRequest( UUID.randomUUID().toString() );
+    }
+
+    @SuppressWarnings("unchecked")
+    private ListenableFuture<RpcResult<NetconfMessage>> sendRequest( String messageID ) throws Exception {
+        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+        Element element = doc.createElement( "request" );
+        element.setAttribute( "message-id", messageID );
+        doc.appendChild( element );
+        NetconfMessage message = new NetconfMessage( doc );
+
+        ChannelFuture mockChannelFuture = mock( ChannelFuture.class );
+        doReturn( mockChannelFuture ).when( mockChannelFuture )
+            .addListener( any( (GenericFutureListener.class ) ) );
+        doReturn( mockChannelFuture ).when( mockSession ).sendMessage( same( message ) );
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture =
+                                      communicator.sendRequest( message, QName.create( "mock rpc" ) );
+
+        assertNotNull( "ListenableFuture is null", resultFuture );
+        return resultFuture;
+    }
+
+    @Test
+    public void testOnSessionUp() {
+        String testCapability = "urn:opendaylight:params:xml:ns:test?module=test-module&revision=2014-06-02";
+        Collection<String> serverCapabilities =
+                Sets.newHashSet( NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString(),
+                                 NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString(),
+                                 testCapability );
+        doReturn( serverCapabilities ).when( mockSession ).getServerCapabilities();
+
+        ArgumentCaptor<NetconfSessionCapabilities> netconfSessionCapabilities =
+                                              ArgumentCaptor.forClass( NetconfSessionCapabilities.class );
+        doNothing().when( mockDevice ).onRemoteSessionUp( netconfSessionCapabilities.capture(), eq( communicator ) );
+
+        communicator.onSessionUp( mockSession );
+
+        verify( mockSession ).getServerCapabilities();
+        verify( mockDevice ).onRemoteSessionUp( netconfSessionCapabilities.capture(), eq( communicator ) );
+
+        NetconfSessionCapabilities actualCapabilites = netconfSessionCapabilities.getValue();
+        assertEquals( "containsCapability", true, actualCapabilites.containsCapability(
+                                NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString() ) );
+        assertEquals( "containsCapability", true, actualCapabilites.containsCapability( testCapability ) );
+        assertEquals( "getModuleBasedCaps", Sets.newHashSet(
+                            QName.create( "urn:opendaylight:params:xml:ns:test", "2014-06-02", "test-module" )),
+                      actualCapabilites.getModuleBasedCaps() );
+        assertEquals( "isRollbackSupported", true, actualCapabilites.isRollbackSupported() );
+        assertEquals( "isMonitoringSupported", true, actualCapabilites.isMonitoringSupported() );
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(timeout=5000)
+    public void testOnSessionDown() throws Exception {
+        setupSession();
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture1 = sendRequest();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture2 = sendRequest();
+
+        doNothing().when( mockDevice ).onRemoteSessionDown();
+
+        communicator.onSessionDown( mockSession, new Exception( "mock ex" ) );
+
+        verifyErrorRpcResult( resultFuture1.get(), RpcError.ErrorType.TRANSPORT, "operation-failed" );
+        verifyErrorRpcResult( resultFuture2.get(), RpcError.ErrorType.TRANSPORT, "operation-failed" );
+
+        verify( mockDevice ).onRemoteSessionDown();
+
+        reset( mockDevice );
+
+        communicator.onSessionDown( mockSession, new Exception( "mock ex" ) );
+
+        verify( mockDevice, never() ).onRemoteSessionDown();
+    }
+
+    @Test
+    public void testOnSessionTerminated() throws Exception {
+        setupSession();
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = sendRequest();
+
+        doNothing().when( mockDevice ).onRemoteSessionDown();
+
+        String reasonText = "testing terminate";
+        NetconfTerminationReason reason = new NetconfTerminationReason( reasonText );
+        communicator.onSessionTerminated( mockSession, reason );
+
+        RpcError rpcError = verifyErrorRpcResult( resultFuture.get(), RpcError.ErrorType.TRANSPORT,
+                                                  "operation-failed" );
+        assertEquals( "RpcError message", reasonText, rpcError.getMessage() );
+
+        verify( mockDevice ).onRemoteSessionDown();
+    }
+
+    @Test
+    public void testClose() throws Exception {
+        communicator.close();
+        verify( mockDevice, never() ).onRemoteSessionDown();
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void testSendRequest() throws Exception {
+        setupSession();
+
+        NetconfMessage message = new NetconfMessage(
+                              DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() );
+        QName rpc = QName.create( "mock rpc" );
+
+        ArgumentCaptor<GenericFutureListener> futureListener =
+                                            ArgumentCaptor.forClass( GenericFutureListener.class );
+
+        ChannelFuture mockChannelFuture = mock( ChannelFuture.class );
+        doReturn( mockChannelFuture ).when( mockChannelFuture ).addListener( futureListener.capture() );
+        doReturn( mockChannelFuture ).when( mockSession ).sendMessage( same( message ) );
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = communicator.sendRequest( message, rpc );
+
+        verify( mockSession ).sendMessage( same( message ) );
+
+        assertNotNull( "ListenableFuture is null", resultFuture );
+
+        verify( mockChannelFuture ).addListener( futureListener.capture() );
+        Future<Void> operationFuture = mock( Future.class );
+        doReturn( true ).when( operationFuture ).isSuccess();
+        doReturn( true ).when( operationFuture ).isDone();
+        futureListener.getValue().operationComplete( operationFuture );
+
+        try {
+            resultFuture.get( 1, TimeUnit.MILLISECONDS ); // verify it's not cancelled or has an error set
+        }
+        catch( TimeoutException e ) {} // expected
+    }
+
+    @Test
+    public void testSendRequestWithNoSession() throws Exception {
+        NetconfMessage message = new NetconfMessage(
+                              DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() );
+        QName rpc = QName.create( "mock rpc" );
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = communicator.sendRequest( message, rpc );
+
+        assertNotNull( "ListenableFuture is null", resultFuture );
+
+        // Should have an immediate result
+        RpcResult<NetconfMessage> rpcResult = resultFuture.get( 3, TimeUnit.MILLISECONDS );
+
+        verifyErrorRpcResult( rpcResult, RpcError.ErrorType.TRANSPORT, "operation-failed" );
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void testSendRequestWithWithSendFailure() throws Exception {
+        setupSession();
+
+        NetconfMessage message = new NetconfMessage(
+                              DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() );
+        QName rpc = QName.create( "mock rpc" );
+
+        ArgumentCaptor<GenericFutureListener> futureListener =
+                                            ArgumentCaptor.forClass( GenericFutureListener.class );
+
+        ChannelFuture mockChannelFuture = mock( ChannelFuture.class );
+        doReturn( mockChannelFuture ).when( mockChannelFuture ).addListener( futureListener.capture() );
+        doReturn( mockChannelFuture ).when( mockSession ).sendMessage( same( message ) );
+
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = communicator.sendRequest( message, rpc );
+
+        assertNotNull( "ListenableFuture is null", resultFuture );
+
+        verify( mockChannelFuture ).addListener( futureListener.capture() );
+
+        Future<Void> operationFuture = mock( Future.class );
+        doReturn( false ).when( operationFuture ).isSuccess();
+        doReturn( true ).when( operationFuture ).isDone();
+        doReturn( new Exception( "mock error" ) ).when( operationFuture ).cause();
+        futureListener.getValue().operationComplete( operationFuture );
+
+        // Should have an immediate result
+        RpcResult<NetconfMessage> rpcResult = resultFuture.get( 3, TimeUnit.MILLISECONDS );
+
+        RpcError rpcError = verifyErrorRpcResult( rpcResult, RpcError.ErrorType.TRANSPORT, "operation-failed" );
+        assertEquals( "RpcError message contains \"mock error\"", true,
+                    rpcError.getMessage().contains( "mock error" ) );
+    }
+
+    private NetconfMessage createSuccessResponseMessage( String messageID ) throws ParserConfigurationException {
+        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+        Element rpcReply = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, RPC_REPLY_KEY );
+        rpcReply.setAttribute( "message-id", messageID );
+        Element element = doc.createElementNS( "ns", "data" );
+        element.setTextContent( messageID );
+        rpcReply.appendChild( element );
+        doc.appendChild( rpcReply );
+
+        return new NetconfMessage( doc );
+    }
+
+    @Test
+    public void testOnSuccessfulResponseMessage() throws Exception {
+        setupSession();
+
+        String messageID1 = UUID.randomUUID().toString();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture1 = sendRequest( messageID1 );
+
+        String messageID2 = UUID.randomUUID().toString();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture2 = sendRequest( messageID2 );
+
+        communicator.onMessage( mockSession, createSuccessResponseMessage( messageID1 ) );
+        communicator.onMessage( mockSession, createSuccessResponseMessage( messageID2 ) );
+
+        verifyResponseMessage( resultFuture1.get(), messageID1 );
+        verifyResponseMessage( resultFuture2.get(), messageID2 );
+    }
+
+    @Test
+    public void testOnResponseMessageWithError() throws Exception {
+        setupSession();
+
+        String messageID = UUID.randomUUID().toString();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = sendRequest( messageID );
+
+        communicator.onMessage( mockSession, createErrorResponseMessage( messageID ) );
+
+        RpcError rpcError = verifyErrorRpcResult( resultFuture.get(), RpcError.ErrorType.RPC,
+                                                  "missing-attribute" );
+        assertEquals( "RpcError message", "Missing attribute", rpcError.getMessage() );
+
+        String errorInfo = rpcError.getInfo();
+        assertNotNull( "RpcError info is null", errorInfo );
+        assertEquals( "Error info contains \"foo\"", true,
+                      errorInfo.contains( "<bad-attribute>foo</bad-attribute>" ) );
+        assertEquals( "Error info contains \"bar\"", true,
+                      errorInfo.contains( "<bad-element>bar</bad-element>" ) );
+    }
+
+    @Test
+    public void testOnResponseMessageWithWrongMessageID() throws Exception {
+        setupSession();
+
+        String messageID = UUID.randomUUID().toString();
+        ListenableFuture<RpcResult<NetconfMessage>> resultFuture = sendRequest( messageID );
+
+        communicator.onMessage( mockSession, createSuccessResponseMessage( UUID.randomUUID().toString() ) );
+
+        RpcError rpcError = verifyErrorRpcResult( resultFuture.get(), RpcError.ErrorType.PROTOCOL,
+                                                  "bad-attribute" );
+        assertEquals( "RpcError message non-empty", true,
+                      !Strings.isNullOrEmpty( rpcError.getMessage() ) );
+
+        String errorInfo = rpcError.getInfo();
+        assertNotNull( "RpcError info is null", errorInfo );
+        assertEquals( "Error info contains \"actual-message-id\"", true,
+                      errorInfo.contains( "actual-message-id" ) );
+        assertEquals( "Error info contains \"expected-message-id\"", true,
+                      errorInfo.contains( "expected-message-id" ) );
+    }
+
+    private NetconfMessage createErrorResponseMessage( String messageID ) throws Exception {
+        String xmlStr =
+            "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"" +
+            "           message-id=\"" + messageID + "\">" +
+            "  <rpc-error>" +
+            "    <error-type>rpc</error-type>" +
+            "    <error-tag>missing-attribute</error-tag>" +
+            "    <error-severity>error</error-severity>" +
+            "    <error-message>Missing attribute</error-message>" +
+            "    <error-info>" +
+            "      <bad-attribute>foo</bad-attribute>" +
+            "      <bad-element>bar</bad-element>" +
+            "    </error-info>" +
+            "  </rpc-error>" +
+            "</rpc-reply>";
+
+        ByteArrayInputStream bis = new ByteArrayInputStream( xmlStr.getBytes() );
+        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( bis );
+        return new NetconfMessage( doc );
+    }
+
+    private void verifyResponseMessage( RpcResult<NetconfMessage> rpcResult, String dataText ) {
+        assertNotNull( "RpcResult is null", rpcResult );
+        assertEquals( "isSuccessful", true, rpcResult.isSuccessful() );
+        NetconfMessage messageResult = rpcResult.getResult();
+        assertNotNull( "getResult", messageResult );
+//        List<SimpleNode<?>> nodes = messageResult.getSimpleNodesByName(
+//                                         QName.create( URI.create( "ns" ), null, "data" ) );
+//        assertNotNull( "getSimpleNodesByName", nodes );
+//        assertEquals( "List<SimpleNode<?>> size", 1, nodes.size() );
+//        assertEquals( "SimpleNode value", dataText, nodes.iterator().next().getValue() );
+    }
+
+    private RpcError verifyErrorRpcResult( RpcResult<NetconfMessage> rpcResult,
+                                           RpcError.ErrorType expErrorType, String expErrorTag ) {
+        assertNotNull( "RpcResult is null", rpcResult );
+        assertEquals( "isSuccessful", false, rpcResult.isSuccessful() );
+        assertNotNull( "RpcResult errors is null", rpcResult.getErrors() );
+        assertEquals( "Errors size", 1, rpcResult.getErrors().size() );
+        RpcError rpcError = rpcResult.getErrors().iterator().next();
+        assertEquals( "getErrorSeverity", RpcError.ErrorSeverity.ERROR, rpcError.getSeverity() );
+        assertEquals( "getErrorType", expErrorType, rpcError.getErrorType() );
+        assertEquals( "getErrorTag", expErrorTag, rpcError.getTag() );
+        assertTrue( "getMessage is empty", StringUtils.isNotEmpty( rpcError.getMessage() ) );
+        return rpcError;
+    }
+}
index 4d9b198795f093c53834f6977447191f2b122136..056be72d4e057b249a17c0286e87b9b0ebe19e72 100644 (file)
@@ -107,13 +107,15 @@ public interface RestconfService {
     @Path("/config/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public StructuredData readConfigurationData(@Encoded @PathParam("identifier") String identifier);
+    public StructuredData readConfigurationData(@Encoded @PathParam("identifier") String identifier,
+                                                @Context UriInfo depth);
 
     @GET
     @Path("/operational/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML,
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public StructuredData readOperationalData(@Encoded @PathParam("identifier") String identifier);
+    public StructuredData readOperationalData(@Encoded @PathParam("identifier") String identifier,
+                                              @Context UriInfo depth);
 
     @PUT
     @Path("/config/{identifier:.+}")
index c0ce90e15dde780a18e40e0e216c78059c9183fc..7b6dcd57dbd7afb223168e6b7c1ad2b8ab87fec5 100644 (file)
@@ -49,6 +49,7 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdent
 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -71,6 +72,7 @@ import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
@@ -566,7 +568,7 @@ public class RestconfImpl implements RestconfService {
     }
 
     @Override
-    public StructuredData readConfigurationData(final String identifier) {
+    public StructuredData readConfigurationData(final String identifier, UriInfo info) {
         final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
         CompositeNode data = null;
         MountInstance mountPoint = iiWithData.getMountPoint();
@@ -577,11 +579,57 @@ public class RestconfImpl implements RestconfService {
             data = broker.readConfigurationData(iiWithData.getInstanceIdentifier());
         }
 
+        data = pruneDataAtDepth( data, parseDepthParameter( info ) );
         return new StructuredData(data, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
     }
 
+    @SuppressWarnings("unchecked")
+    private <T extends Node<?>> T pruneDataAtDepth( T node, Integer depth ) {
+        if( depth == null ) {
+            return node;
+        }
+
+        if( node instanceof CompositeNode ) {
+            ImmutableList.Builder<Node<?>> newChildNodes = ImmutableList.<Node<?>> builder();
+            if( depth > 1 ) {
+                for( Node<?> childNode: ((CompositeNode)node).getValue() ) {
+                    newChildNodes.add( pruneDataAtDepth( childNode, depth - 1 ) );
+                }
+            }
+
+            return (T) ImmutableCompositeNode.create( node.getNodeType(), newChildNodes.build() );
+        }
+        else { // SimpleNode
+            return node;
+        }
+    }
+
+    private Integer parseDepthParameter( UriInfo info ) {
+        String param = info.getQueryParameters( false ).getFirst( "depth" );
+        if( Strings.isNullOrEmpty( param ) || "unbounded".equals( param ) ) {
+            return null;
+        }
+
+        try {
+            Integer depth = Integer.valueOf( param );
+            if( depth < 1 ) {
+                throw new RestconfDocumentedException( new RestconfError(
+                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, "Invalid depth parameter: " + depth,
+                        null, "The depth parameter must be an integer > 1 or \"unbounded\"" ) );
+            }
+
+            return depth;
+        }
+        catch( NumberFormatException e ) {
+            throw new RestconfDocumentedException( new RestconfError(
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
+                    "Invalid depth parameter: " + e.getMessage(),
+                    null, "The depth parameter must be an integer > 1 or \"unbounded\"" ) );
+        }
+    }
+
     @Override
-    public StructuredData readOperationalData(final String identifier) {
+    public StructuredData readOperationalData(final String identifier, UriInfo info) {
         final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
         CompositeNode data = null;
         MountInstance mountPoint = iiWithData.getMountPoint();
@@ -592,6 +640,7 @@ public class RestconfImpl implements RestconfService {
             data = broker.readOperationalData(iiWithData.getInstanceIdentifier());
         }
 
+        data = pruneDataAtDepth( data, parseDepthParameter( info ) );
         return new StructuredData(data, iiWithData.getSchemaNode(), mountPoint);
     }
 
index 2037fd4862f3c71f5f8a180f8c5509f7cbda23a4..319603dfc14b1f6a4965d6de46e99bf1a6199f8f 100644 (file)
@@ -23,6 +23,7 @@ import java.io.UnsupportedEncodingException;
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
 
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
@@ -96,21 +97,21 @@ public class MediaTypesTest extends JerseyTest {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
         String uri = uriPrefix + uriPath;
-        when(restconfService.readConfigurationData(uriPath)).thenReturn(null);
+        when(restconfService.readConfigurationData(eq(uriPath), any(UriInfo.class))).thenReturn(null);
         get(uri, Draft02.MediaTypes.DATA+JSON);
-        verify(restconfService, times(1)).readConfigurationData(uriPath);
+        verify(restconfService, times(1)).readConfigurationData(eq(uriPath), any(UriInfo.class));
         get(uri, Draft02.MediaTypes.DATA+XML);
-        verify(restconfService, times(2)).readConfigurationData(uriPath);
+        verify(restconfService, times(2)).readConfigurationData(eq(uriPath), any(UriInfo.class));
         get(uri, MediaType.APPLICATION_JSON);
-        verify(restconfService, times(3)).readConfigurationData(uriPath);
+        verify(restconfService, times(3)).readConfigurationData(eq(uriPath), any(UriInfo.class));
         get(uri, MediaType.APPLICATION_XML);
-        verify(restconfService, times(4)).readConfigurationData(uriPath);
+        verify(restconfService, times(4)).readConfigurationData(eq(uriPath), any(UriInfo.class));
         get(uri, MediaType.TEXT_XML);
-        verify(restconfService, times(5)).readConfigurationData(uriPath);
+        verify(restconfService, times(5)).readConfigurationData(eq(uriPath), any(UriInfo.class));
 
         // negative tests
         get(uri, MediaType.TEXT_PLAIN);
-        verify(restconfService, times(5)).readConfigurationData(uriPath);
+        verify(restconfService, times(5)).readConfigurationData(eq(uriPath), any(UriInfo.class));
     }
 
     @Test
@@ -118,21 +119,21 @@ public class MediaTypesTest extends JerseyTest {
         String uriPrefix = "/operational/";
         String uriPath = "ietf-interfaces:interfaces";
         String uri = uriPrefix + uriPath;
-        when(restconfService.readOperationalData(uriPath)).thenReturn(null);
+        when(restconfService.readOperationalData(eq(uriPath), any(UriInfo.class))).thenReturn(null);
         get(uri, Draft02.MediaTypes.DATA+JSON);
-        verify(restconfService, times(1)).readOperationalData(uriPath);
+        verify(restconfService, times(1)).readOperationalData(eq(uriPath), any(UriInfo.class));
         get(uri, Draft02.MediaTypes.DATA+XML);
-        verify(restconfService, times(2)).readOperationalData(uriPath);
+        verify(restconfService, times(2)).readOperationalData(eq(uriPath), any(UriInfo.class));
         get(uri, MediaType.APPLICATION_JSON);
-        verify(restconfService, times(3)).readOperationalData(uriPath);
+        verify(restconfService, times(3)).readOperationalData(eq(uriPath), any(UriInfo.class));
         get(uri, MediaType.APPLICATION_XML);
-        verify(restconfService, times(4)).readOperationalData(uriPath);
+        verify(restconfService, times(4)).readOperationalData(eq(uriPath), any(UriInfo.class));
         get(uri, MediaType.TEXT_XML);
-        verify(restconfService, times(5)).readOperationalData(uriPath);
+        verify(restconfService, times(5)).readOperationalData(eq(uriPath), any(UriInfo.class));
 
         // negative tests
         get(uri, MediaType.TEXT_PLAIN);
-        verify(restconfService, times(5)).readOperationalData(uriPath);
+        verify(restconfService, times(5)).readOperationalData(eq(uriPath), any(UriInfo.class));
     }
 
     @Test
index 893622f60a18ae8a0b8e5e394f9631d0f418374c..f0a232fba670539c5a872e5894a89bd7c214c778 100644 (file)
@@ -7,15 +7,17 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.io.FileNotFoundException;
+import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -24,17 +26,23 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountService;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
@@ -45,6 +53,7 @@ import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
 import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -52,10 +61,28 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 public class RestGetOperationTest extends JerseyTest {
 
+    static class NodeData {
+        Object key;
+        Object data; // List for a CompositeNode, value Object for a SimpleNode
+
+        NodeData( Object key, Object data ) {
+            this.key = key;
+            this.data = data;
+        }
+    }
+
     private static BrokerFacade brokerFacade;
     private static RestconfImpl restconfImpl;
     private static SchemaContext schemaContextYangsIetf;
@@ -588,4 +615,314 @@ public class RestGetOperationTest extends JerseyTest {
         return null;
     }
 
+    @Test
+    public void getDataWithUriDepthParameterTest() throws UnsupportedEncodingException {
+
+        ControllerContext.getInstance().setGlobalSchema( schemaContextModules );
+
+        CompositeNode depth1Cont = toCompositeNode(
+            toCompositeNodeData( toNestedQName( "depth1-cont" ),
+                toCompositeNodeData( toNestedQName( "depth2-cont1" ),
+                    toCompositeNodeData( toNestedQName( "depth3-cont1" ),
+                        toCompositeNodeData( toNestedQName( "depth4-cont1" ),
+                            toSimpleNodeData( toNestedQName( "depth5-leaf1" ), "depth5-leaf1-value" )
+                        ),
+                        toSimpleNodeData( toNestedQName( "depth4-leaf1" ), "depth4-leaf1-value" )
+                    ),
+                    toSimpleNodeData( toNestedQName( "depth3-leaf1" ), "depth3-leaf1-value" )
+                ),
+                toCompositeNodeData( toNestedQName( "depth2-cont2" ),
+                    toCompositeNodeData( toNestedQName( "depth3-cont2" ),
+                        toCompositeNodeData( toNestedQName( "depth4-cont2" ),
+                            toSimpleNodeData( toNestedQName( "depth5-leaf2" ), "depth5-leaf2-value" )
+                        ),
+                        toSimpleNodeData( toNestedQName( "depth4-leaf2" ), "depth4-leaf2-value" )
+                    ),
+                    toSimpleNodeData( toNestedQName( "depth3-leaf2" ), "depth3-leaf2-value" )
+                ),
+                toSimpleNodeData( toNestedQName( "depth2-leaf1" ), "depth2-leaf1-value" )
+            ) );
+
+        when( brokerFacade.readConfigurationData( any( InstanceIdentifier.class ) ) )
+            .thenReturn( depth1Cont );
+
+        // Test config with depth 1
+
+        Response response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "1" )
+                                .request( "application/xml" ).get();
+
+        verifyXMLResponse( response, expectEmptyContainer( "depth1-cont" ) );
+
+        // Test config with depth 2
+
+        response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "2" )
+                       .request( "application/xml" ).get();
+
+//        String xml="<depth1-cont><depth2-cont1/><depth2-cont2/><depth2-leaf1>depth2-leaf1-value</depth2-leaf1></depth1-cont>";
+//        Response mr=mock(Response.class);
+//        when(mr.getEntity()).thenReturn( new java.io.StringBufferInputStream(xml) );
+
+        verifyXMLResponse( response,
+            expectContainer( "depth1-cont",
+                expectEmptyContainer( "depth2-cont1" ),
+                expectEmptyContainer( "depth2-cont2" ),
+                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+            ) );
+
+        // Test config with depth 3
+
+        response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "3" )
+                       .request( "application/xml" ).get();
+
+        verifyXMLResponse( response,
+            expectContainer( "depth1-cont",
+                expectContainer( "depth2-cont1",
+                    expectEmptyContainer( "depth3-cont1" ),
+                    expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                ),
+                expectContainer( "depth2-cont2",
+                    expectEmptyContainer( "depth3-cont2" ),
+                    expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
+                ),
+                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+           ) );
+
+        // Test config with depth 4
+
+        response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "4" )
+                      .request( "application/xml" ).get();
+
+        verifyXMLResponse( response,
+            expectContainer( "depth1-cont",
+                expectContainer( "depth2-cont1",
+                    expectContainer( "depth3-cont1",
+                        expectEmptyContainer( "depth4-cont1" ),
+                        expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
+                    ),
+                    expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                ),
+                expectContainer( "depth2-cont2",
+                    expectContainer( "depth3-cont2",
+                        expectEmptyContainer( "depth4-cont2" ),
+                        expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
+                    ),
+                    expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
+                ),
+                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+            ) );
+
+        // Test config with depth 5
+
+        response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "5" )
+                       .request( "application/xml" ).get();
+
+        verifyXMLResponse( response,
+            expectContainer( "depth1-cont",
+                expectContainer( "depth2-cont1",
+                    expectContainer( "depth3-cont1",
+                        expectContainer( "depth4-cont1",
+                            expectLeaf( "depth5-leaf1", "depth5-leaf1-value" )
+                        ),
+                        expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
+                    ),
+                    expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                ),
+                expectContainer( "depth2-cont2",
+                    expectContainer( "depth3-cont2",
+                        expectContainer( "depth4-cont2",
+                            expectLeaf( "depth5-leaf2", "depth5-leaf2-value" )
+                        ),
+                        expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
+                    ),
+                    expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
+                ),
+                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+            ) );
+
+        // Test config with depth unbounded
+
+        response = target( "/config/nested-module:depth1-cont" ).queryParam( "depth", "unbounded" )
+                       .request( "application/xml" ).get();
+
+        verifyXMLResponse( response,
+            expectContainer( "depth1-cont",
+                expectContainer( "depth2-cont1",
+                    expectContainer( "depth3-cont1",
+                        expectContainer( "depth4-cont1",
+                            expectLeaf( "depth5-leaf1", "depth5-leaf1-value" )
+                        ),
+                        expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
+                    ),
+                    expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+                ),
+                expectContainer( "depth2-cont2",
+                    expectContainer( "depth3-cont2",
+                        expectContainer( "depth4-cont2",
+                            expectLeaf( "depth5-leaf2", "depth5-leaf2-value" )
+                        ),
+                        expectLeaf( "depth4-leaf2", "depth4-leaf2-value" )
+                    ),
+                    expectLeaf( "depth3-leaf2", "depth3-leaf2-value" )
+                ),
+                expectLeaf( "depth2-leaf1", "depth2-leaf1-value" )
+            ) );
+
+        // Test operational
+
+        CompositeNode depth2Cont1 = toCompositeNode(
+            toCompositeNodeData( toNestedQName( "depth2-cont1" ),
+                toCompositeNodeData( toNestedQName( "depth3-cont1" ),
+                    toCompositeNodeData( toNestedQName( "depth4-cont1" ),
+                        toSimpleNodeData( toNestedQName( "depth5-leaf1" ), "depth5-leaf1-value" )
+                    ),
+                    toSimpleNodeData( toNestedQName( "depth4-leaf1" ), "depth4-leaf1-value" )
+                ),
+                toSimpleNodeData( toNestedQName( "depth3-leaf1" ), "depth3-leaf1-value" )
+            ) );
+
+        when( brokerFacade.readOperationalData( any( InstanceIdentifier.class ) ) )
+             .thenReturn( depth2Cont1 );
+
+        response = target( "/operational/nested-module:depth1-cont/depth2-cont1" )
+                       .queryParam( "depth", "3" ).request( "application/xml" ).get();
+
+        verifyXMLResponse( response,
+            expectContainer( "depth2-cont1",
+                expectContainer( "depth3-cont1",
+                    expectEmptyContainer( "depth4-cont1" ),
+                    expectLeaf( "depth4-leaf1", "depth4-leaf1-value" )
+                ),
+                expectLeaf( "depth3-leaf1", "depth3-leaf1-value" )
+            ) );
+    }
+
+    @Test
+    public void getDataWithInvalidDepthParameterTest() {
+
+        ControllerContext.getInstance().setGlobalSchema( schemaContextModules );
+
+        final MultivaluedMap<String,String> paramMap = new MultivaluedHashMap<>();
+        paramMap.putSingle( "depth", "1o" );
+        UriInfo mockInfo = mock( UriInfo.class );
+        when( mockInfo.getQueryParameters( false ) ).thenAnswer(
+            new Answer<MultivaluedMap<String,String>>() {
+                @Override
+                public MultivaluedMap<String, String> answer( InvocationOnMock invocation ) {
+                    return paramMap;
+                }
+            } );
+
+        getDataWithInvalidDepthParameterTest( mockInfo );
+
+        paramMap.putSingle( "depth", "0" );
+        getDataWithInvalidDepthParameterTest( mockInfo );
+
+        paramMap.putSingle( "depth", "-1" );
+        getDataWithInvalidDepthParameterTest( mockInfo );
+    }
+
+    private void getDataWithInvalidDepthParameterTest( UriInfo uriInfo ) {
+        try {
+            restconfImpl.readConfigurationData( "nested-module:depth1-cont", uriInfo );
+            fail( "Expected RestconfDocumentedException" );
+        }
+        catch( RestconfDocumentedException e ) {
+            assertTrue( "Unexpected error message: " + e.getErrors().get( 0 ).getErrorMessage(),
+                        e.getErrors().get( 0 ).getErrorMessage().contains( "depth" ) );
+        }
+    }
+
+    private void verifyXMLResponse( Response response, NodeData nodeData ) {
+
+        Document doc = TestUtils.loadDocumentFrom( (InputStream) response.getEntity() );
+        assertNotNull( "Could not parse XML document", doc );
+
+        //System.out.println(TestUtils.getDocumentInPrintableForm( doc ));
+
+        verifyContainerElement( doc.getDocumentElement(), nodeData );
+    }
+
+    @SuppressWarnings("unchecked")
+    private void verifyContainerElement( Element element, NodeData nodeData ) {
+
+        assertEquals( "Element local name", nodeData.key, element.getNodeName() );
+
+        NodeList childNodes = element.getChildNodes();
+        if( nodeData.data == null ) { // empty container
+            assertTrue( "Expected no child elements for \"" + element.getNodeName() + "\"",
+                        childNodes.getLength() == 0 );
+            return;
+        }
+
+        Map<String,NodeData> expChildMap = Maps.newHashMap();
+        for( NodeData expChild: (List<NodeData>)nodeData.data ) {
+            expChildMap.put( expChild.key.toString(), expChild );
+        }
+
+        for( int i = 0; i < childNodes.getLength(); i++ ) {
+            org.w3c.dom.Node actualChild = childNodes.item( i );
+            if( !( actualChild instanceof Element ) ) {
+                continue;
+            }
+
+            Element actualElement = (Element)actualChild;
+            NodeData expChild = expChildMap.remove( actualElement.getNodeName() );
+            assertNotNull( "Unexpected child element for parent \"" + element.getNodeName() +
+                           "\": " + actualElement.getNodeName(), expChild );
+
+            if( expChild.data == null || expChild.data instanceof List ) {
+                verifyContainerElement( actualElement, expChild );
+            }
+            else {
+                assertEquals( "Text content for element: " + actualElement.getNodeName(),
+                              expChild.data, actualElement.getTextContent() );
+            }
+        }
+
+        if( !expChildMap.isEmpty() ) {
+            fail( "Missing elements for parent \"" + element.getNodeName() +
+                  "\": " + expChildMap.keySet() );
+        }
+    }
+
+    private NodeData expectContainer( String name, NodeData... childData ) {
+        return new NodeData( name, Lists.newArrayList( childData ) );
+    }
+
+    private NodeData expectEmptyContainer( String name ) {
+        return new NodeData( name, null );
+    }
+
+    private NodeData expectLeaf( String name, Object value ) {
+        return new NodeData( name, value );
+    }
+
+    private QName toNestedQName( String localName ) {
+        return QName.create( "urn:nested:module", "2014-06-3", localName );
+    }
+
+    @SuppressWarnings("unchecked")
+    private CompositeNode toCompositeNode( NodeData nodeData ) {
+        CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
+        builder.setQName( (QName) nodeData.key );
+
+        for( NodeData child: (List<NodeData>)nodeData.data ) {
+            if( child.data instanceof List ) {
+                builder.add( toCompositeNode( child ) );
+            }
+            else {
+                builder.addLeaf( (QName) child.key, child.data );
+            }
+        }
+
+        return builder.toInstance();
+    }
+
+    private NodeData toCompositeNodeData( QName key, NodeData... childData ) {
+        return new NodeData( key, Lists.newArrayList( childData ) );
+    }
+
+    private NodeData toSimpleNodeData( QName key, Object value ) {
+        return new NodeData( key, value );
+    }
 }
index 3f984c293b333563de6d696065e26645d1940982..e146cf8f4fa165a4d3234b616e3bbad1516004e1 100644 (file)
@@ -34,6 +34,7 @@ import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.xpath.XPath;
@@ -220,7 +221,7 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
 
     void stageMockEx( final RestconfDocumentedException ex ) {
         reset( mockRestConf );
-        when( mockRestConf.readOperationalData( any( String.class ) ) ).thenThrow( ex );
+        when( mockRestConf.readOperationalData( any( String.class ), any( UriInfo.class ) ) ).thenThrow( ex );
     }
 
     void testJsonResponse( final RestconfDocumentedException ex, final Status expStatus, final ErrorType expErrorType,
@@ -776,8 +777,8 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
 
         // The StructuredDataToJsonProvider should throw a RestconfDocumentedException with no data
 
-        when( mockRestConf.readOperationalData( any( String.class ) ) )
-        .thenReturn( new StructuredData( null, null, null ) );
+        when( mockRestConf.readOperationalData( any( String.class ), any( UriInfo.class ) ) )
+            .thenReturn( new StructuredData( null, null, null ) );
 
         Response resp = target("/operational/foo").request( MediaType.APPLICATION_JSON ).get();
 
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/modules/nested-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/modules/nested-module.yang
new file mode 100644 (file)
index 0000000..590743c
--- /dev/null
@@ -0,0 +1,47 @@
+module nested-module {
+    namespace "urn:nested:module";
+    prefix "nested";
+    revision "2014-06-3";
+
+    container depth1-cont {
+        container depth2-cont1 {
+            container depth3-cont1 {
+                container depth4-cont1 {
+                    leaf depth5-leaf1 {
+                        type string;
+                    }
+                }
+                
+                leaf depth4-leaf1 {
+                    type string;
+                }
+            }
+            
+            leaf depth3-leaf1 {
+                type string;
+            }
+        }
+        
+        container depth2-cont2 {
+            container depth3-cont2 {
+                container depth4-cont2 {
+                    leaf depth5-leaf2 {
+                        type string;
+                    }
+                }
+                
+                leaf depth4-leaf2 {
+                    type string;
+                }
+            }
+            
+            leaf depth3-leaf2 {
+                type string;
+            }
+        }
+        
+        leaf depth2-leaf1 {
+            type string;
+        }
+    }
+} 
\ No newline at end of file
index 8954c058116639b6dae8af9227930209fcfdb81e..79a3434c497e2e3773a75cdaf7238f4cbf0a3b97 100644 (file)
       <artifactId>guava</artifactId>
     </dependency>
 
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.3.2</version>
+      <!--$NO-MVN-MAN-VER$ -->
+    </dependency>
+
     <!-- Jax rs -->
     <dependency>
       <groupId>org.jboss.resteasy</groupId>
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
index 934412d95af1dce17b281e1b6c6e0f1e0a380bb7..31f4253318f146e95c2a0923f3f08d3e14cc4a2d 100644 (file)
@@ -9,11 +9,17 @@ package org.opendaylight.controller.sal.rest.doc;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService.MountProvisionListener;
 import org.opendaylight.controller.sal.rest.doc.impl.ApiDocGenerator;
+import org.opendaylight.controller.sal.rest.doc.mountpoints.MountPointSwagger;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -22,24 +28,37 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class DocProvider implements BundleActivator, ServiceTrackerCustomizer<Broker, Broker>, Provider, AutoCloseable {
+public class DocProvider implements BundleActivator, ServiceTrackerCustomizer<Broker, Broker>,
+        Provider, AutoCloseable {
 
-    private static final Logger _logger = LoggerFactory.getLogger(DocProvider.class);
+    private final Logger _logger = LoggerFactory.getLogger(DocProvider.class);
 
     private ServiceTracker<Broker, Broker> brokerServiceTracker;
     private BundleContext bundleContext;
     private Broker.ProviderSession session;
 
+    private final List<AutoCloseable> toClose = new LinkedList<>();
+
     @Override
     public void close() throws Exception {
         stop(bundleContext);
     }
 
     @Override
-    public void onSessionInitiated(final Broker.ProviderSession providerSession) {
+    public void onSessionInitiated(Broker.ProviderSession providerSession) {
         SchemaService schemaService = providerSession.getService(SchemaService.class);
         ApiDocGenerator.getInstance().setSchemaService(schemaService);
 
+        MountProvisionService mountService = providerSession
+                .getService(MountProvisionService.class);
+        ListenerRegistration<MountProvisionListener> registration = mountService
+                .registerProvisionListener(MountPointSwagger.getInstance());
+        MountPointSwagger.getInstance().setGlobalSchema(schemaService);
+        synchronized (toClose) {
+            toClose.add(registration);
+        }
+        MountPointSwagger.getInstance().setMountService(mountService);
+
         _logger.debug("Restconf API Explorer started");
     }
 
@@ -49,42 +68,45 @@ public class DocProvider implements BundleActivator, ServiceTrackerCustomizer<Br
     }
 
     @Override
-    public void start(final BundleContext context) throws Exception {
+    public void start(BundleContext context) throws Exception {
         bundleContext = context;
-        brokerServiceTracker = new ServiceTracker<>(context, Broker.class, this);
+        brokerServiceTracker = new ServiceTracker(context, Broker.class, this);
         brokerServiceTracker.open();
     }
 
     @Override
-    public void stop(final BundleContext context) throws Exception {
-        if (brokerServiceTracker != null) {
+    public void stop(BundleContext context) throws Exception {
+        if (brokerServiceTracker != null)
             brokerServiceTracker.close();
-        }
 
-        if (session != null) {
+        if (session != null)
             session.close();
+
+        synchronized (toClose) {
+            for (AutoCloseable close : toClose) {
+                close.close();
+            }
         }
     }
 
     @Override
-    public Broker addingService(final ServiceReference<Broker> reference) {
+    public Broker addingService(ServiceReference<Broker> reference) {
         Broker broker = bundleContext.getService(reference);
         session = broker.registerProvider(this, bundleContext);
         return broker;
     }
 
     @Override
-    public void modifiedService(final ServiceReference<Broker> reference, final Broker service) {
-        if (session != null) {
+    public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+        if (session != null)
             session.close();
-        }
 
         Broker broker = bundleContext.getService(reference);
         session = broker.registerProvider(this, bundleContext);
     }
 
     @Override
-    public void removedService(final ServiceReference<Broker> reference, final Broker service) {
+    public void removedService(ServiceReference<Broker> reference, Broker service) {
         bundleContext.ungetService(reference);
     }
 }
index 3542d6aadceeff15659a315c306306d6b68ab7c9..2646a6a245210d51198570b4dac8797b45be0a4a 100644 (file)
@@ -16,47 +16,83 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 /**
- * This service generates swagger
- * (See <a href="https://helloreverb.com/developers/swagger">https://helloreverb.com/developers/swagger</a>)
- * compliant documentation for RESTCONF APIs. The output of this is used by embedded Swagger UI.
+ * This service generates swagger (See <a
+ * href="https://helloreverb.com/developers/swagger"
+ * >https://helloreverb.com/developers/swagger</a>) compliant documentation for
+ * RESTCONF APIs. The output of this is used by embedded Swagger UI.
  */
 @Path("/")
 public interface ApiDocService {
 
-  /**
-   * Generates index document for Swagger UI. This document lists out all modules with link to get APIs for
-   * each module. The API for each module is served by <code> getDocByModule()</code> method.
-   *
-   * @param uriInfo
-   * @return
-   */
-  @GET
-  @Produces(MediaType.APPLICATION_JSON)
-  public Response getRootDoc(@Context javax.ws.rs.core.UriInfo uriInfo);
-
-  /**
-   * Generates Swagger compliant document listing APIs for module.
-   *
-   * @param module
-   * @param revision
-   * @param uriInfo
-   * @return
-   */
-  @GET
-  @Path("/{module},{revision}")
-  @Produces(MediaType.APPLICATION_JSON)
-  public Response getDocByModule(@PathParam("module") String module,
-                                 @PathParam("revision") String revision,
-                                 @Context javax.ws.rs.core.UriInfo uriInfo);
-
-  /**
-   * Redirects to embedded swagger ui.
-   *
-   * @param uriInfo
-   * @return
-   */
-  @GET
-  @Path("/ui")
-  @Produces(MediaType.TEXT_HTML)
-  public Response getApiExplorer(@Context javax.ws.rs.core.UriInfo uriInfo);
+    /**
+     * Generates index document for Swagger UI. This document lists out all
+     * modules with link to get APIs for each module. The API for each module is
+     * served by <code> getDocByModule()</code> method.
+     *
+     * @param uriInfo
+     * @return
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getRootDoc(@Context javax.ws.rs.core.UriInfo uriInfo);
+
+    /**
+     * Generates Swagger compliant document listing APIs for module.
+     *
+     * @param module
+     * @param revision
+     * @param uriInfo
+     * @return
+     */
+    @GET
+    @Path("/{module}({revision})")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getDocByModule(@PathParam("module") String module,
+            @PathParam("revision") String revision, @Context javax.ws.rs.core.UriInfo uriInfo);
+
+    /**
+     * Redirects to embedded swagger ui.
+     *
+     * @param uriInfo
+     * @return
+     */
+    @GET
+    @Path("/ui")
+    @Produces(MediaType.TEXT_HTML)
+    public Response getApiExplorer(@Context javax.ws.rs.core.UriInfo uriInfo);
+
+    /**
+     * Generates index document for Swagger UI. This document lists out all
+     * modules with link to get APIs for each module. The API for each module is
+     * served by <code> getDocByModule()</code> method.
+     *
+     * @param uriInfo
+     * @return
+     */
+    @GET
+    @Path("/mounts")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getListOfMounts(@Context javax.ws.rs.core.UriInfo uriInfo);
+
+    @GET
+    @Path("/mounts/{instance}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getMountRootDoc(@PathParam("instance") String instanceNum,
+            @Context javax.ws.rs.core.UriInfo uriInfo);
+
+    /**
+     * Generates Swagger compliant document listing APIs for module.
+     *
+     * @param module
+     * @param revision
+     * @param uriInfo
+     * @return
+     */
+    @GET
+    @Path("/mounts/{instance}/{module}({revision})")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getMountDocByModule(@PathParam("instance") String instanceNum,
+            @PathParam("module") String module, @PathParam("revision") String revision,
+            @Context javax.ws.rs.core.UriInfo uriInfo);
+
 }
index bcd11bcb06633bd939de00a2af513353cf1b1f2d..82409d2e4033050833c7285927e5db23d0d20fc6 100644 (file)
@@ -7,76 +7,44 @@
  */
 package org.opendaylight.controller.sal.rest.doc.impl;
 
-import java.io.IOException;
-import java.net.URI;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import javax.ws.rs.core.UriInfo;
 
-import org.json.JSONException;
-import org.json.JSONObject;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.rest.doc.model.builder.OperationBuilder;
-import org.opendaylight.controller.sal.rest.doc.swagger.Api;
 import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
-import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
-import org.opendaylight.controller.sal.rest.doc.swagger.Parameter;
-import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
 import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
 import com.google.common.base.Preconditions;
 
 /**
- * This class gathers all yang defined {@link Module}s and generates Swagger compliant documentation.
+ * This class gathers all yang defined {@link Module}s and generates Swagger
+ * compliant documentation.
  */
-public class ApiDocGenerator {
+public class ApiDocGenerator extends BaseYangSwaggerGenerator {
 
-    private static final Logger _logger = LoggerFactory.getLogger(ApiDocGenerator.class);
+    private static Logger _logger = LoggerFactory.getLogger(ApiDocGenerator.class);
 
     private static final ApiDocGenerator INSTANCE = new ApiDocGenerator();
-    private final ObjectMapper mapper = new ObjectMapper();
-    private final ModelGenerator jsonConverter = new ModelGenerator();
-
     private SchemaService schemaService;
 
-    private static final String API_VERSION = "1.0.0";
-    private static final String SWAGGER_VERSION = "1.2";
-    private static final String RESTCONF_CONTEXT_ROOT = "restconf";
-    private final DateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
-
-    //For now its {@link HashMap}. It will be changed to thread-safe Map when schema change listener is implemented.
-    private final Map<String, ApiDeclaration> MODULE_DOC_CACHE = new HashMap<String, ApiDeclaration>();
+    public ResourceList getResourceListing(UriInfo uriInfo) {
+        Preconditions.checkState(schemaService != null);
+        SchemaContext schemaContext = schemaService.getGlobalContext();
+        Preconditions.checkState(schemaContext != null);
+        return super.getResourceListing(uriInfo, schemaContext, "");
+    }
 
-    private ApiDocGenerator(){
-        mapper.registerModule(new JsonOrgModule());
-        mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
+    public ApiDeclaration getApiDeclaration(String module, String revision, UriInfo uriInfo) {
+        SchemaContext schemaContext = schemaService.getGlobalContext();
+        Preconditions.checkState(schemaContext != null);
+        return super.getApiDeclaration(module, revision, uriInfo, schemaContext, "");
     }
 
     /**
      * Returns singleton instance
+     *
      * @return
      */
     public static ApiDocGenerator getInstance() {
@@ -87,240 +55,7 @@ public class ApiDocGenerator {
      *
      * @param schemaService
      */
-    public void setSchemaService(final SchemaService schemaService) {
+    public void setSchemaService(SchemaService schemaService) {
         this.schemaService = schemaService;
     }
-    /**
-     *
-     * @param uriInfo
-     * @return  list of modules converted to swagger compliant resource list.
-     */
-    public ResourceList getResourceListing(final UriInfo uriInfo) {
-
-        Preconditions.checkState(schemaService != null);
-        SchemaContext schemaContext = schemaService.getGlobalContext();
-        Preconditions.checkState(schemaContext != null);
-
-        Set<Module> modules = schemaContext.getModules();
-
-        ResourceList resourceList = new ResourceList();
-        resourceList.setApiVersion(API_VERSION);
-        resourceList.setSwaggerVersion(SWAGGER_VERSION);
-
-        List<Resource> resources = new ArrayList<>(modules.size());
-        _logger.info("Modules found [{}]", modules.size());
-
-        for (Module module : modules) {
-            Resource resource = new Resource();
-            String revisionString = SIMPLE_DATE_FORMAT.format(module.getRevision());
-
-            _logger.debug("Working on [{},{}]...", module.getName(), revisionString);
-            ApiDeclaration doc = getApiDeclaration(module.getName(), revisionString, uriInfo);
-
-            if (doc != null) {
-                URI uri = uriInfo.getRequestUriBuilder().
-                        path(generateCacheKey(module.getName(), revisionString)).
-                        build();
-
-                resource.setPath(uri.toASCIIString());
-                resources.add(resource);
-            } else {
-                _logger.debug("Could not generate doc for {},{}", module.getName(), revisionString);
-            }
-        }
-
-        resourceList.setApis(resources);
-
-        return resourceList;
-    }
-
-    public ApiDeclaration getApiDeclaration(final String module, final String revision, final UriInfo uriInfo) {
-
-        //Lookup cache
-        String cacheKey = generateCacheKey(module, revision);
-
-        if (MODULE_DOC_CACHE.containsKey(cacheKey)) {
-            _logger.debug("Serving from cache for {}", cacheKey);
-            return MODULE_DOC_CACHE.get(cacheKey);
-        }
-
-        Date rev = null;
-        try {
-            rev = SIMPLE_DATE_FORMAT.parse(revision);
-        } catch (ParseException e) {
-            throw new IllegalArgumentException(e);
-        }
-
-        SchemaContext schemaContext = schemaService.getGlobalContext();
-        Preconditions.checkState(schemaContext != null);
-
-        Module m = schemaContext.findModuleByName(module, rev);
-        Preconditions.checkArgument(m != null, "Could not find module by name,revision: " + module + "," + revision);
-
-        String basePath = new StringBuilder(uriInfo.getBaseUri().getScheme())
-        .append("://")
-        .append(uriInfo.getBaseUri().getHost())
-        .append(":")
-        .append(uriInfo.getBaseUri().getPort())
-        .append("/")
-        .append(RESTCONF_CONTEXT_ROOT)
-        .toString();
-
-        ApiDeclaration doc = getSwaggerDocSpec(m, basePath);
-        MODULE_DOC_CACHE.put(cacheKey, doc);
-        return doc;
-    }
-
-    public ApiDeclaration getSwaggerDocSpec(final Module m, final String basePath) {
-        ApiDeclaration doc = new ApiDeclaration();
-        doc.setApiVersion(API_VERSION);
-        doc.setSwaggerVersion(SWAGGER_VERSION);
-        doc.setBasePath(basePath);
-        doc.setProduces(Arrays.asList("application/json", "application/xml"));
-
-        List<Api> apis = new ArrayList<Api>();
-
-        Set<DataSchemaNode> dataSchemaNodes = m.getChildNodes();
-        _logger.debug("child nodes size [{}]", dataSchemaNodes.size());
-        for (DataSchemaNode node : dataSchemaNodes) {
-            if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) {
-
-                _logger.debug("Is Configuration node [{}] [{}]", node.isConfiguration(), node.getQName().getLocalName());
-
-                List<Parameter> pathParams = null;
-                if (node.isConfiguration()) {
-                    pathParams = new ArrayList<Parameter>();
-                    String resourcePath = "/config/" + m.getName() + ":";
-                    addApis(node, apis, resourcePath, pathParams, true);
-
-                }
-
-                pathParams = new ArrayList<Parameter>();
-                String resourcePath = "/operational/" + m.getName() + ":";
-                addApis(node, apis, resourcePath, pathParams, false);
-            }
-        }
-
-        Set<RpcDefinition> rpcs = m.getRpcs();
-        for (RpcDefinition rpcDefinition : rpcs) {
-            String resourcePath = "/operations/" + m.getName() + ":";
-            addRpcs(rpcDefinition, apis, resourcePath);
-
-        }
-        _logger.debug("Number of APIs found [{}]", apis.size());
-        doc.setApis(apis);
-        JSONObject models = null;
-
-        try {
-            models = jsonConverter.convertToJsonSchema(m);
-            doc.setModels(models);
-            _logger.debug(mapper.writeValueAsString(doc));
-        } catch (IOException | JSONException e) {
-            e.printStackTrace();
-        }
-
-        return doc;
-    }
-
-    private String generateCacheKey(final Module m) {
-        return generateCacheKey(m.getName(), SIMPLE_DATE_FORMAT.format(m.getRevision()));
-    }
-
-    private String generateCacheKey(final String module, final String revision) {
-        return module + "," + revision;
-    }
-
-    private void addApis(final DataSchemaNode node,
-            final List<Api> apis,
-            final String parentPath,
-            final List<Parameter> parentPathParams,
-            final boolean addConfigApi) {
-
-        Api api = new Api();
-        List<Parameter> pathParams = new ArrayList<Parameter>(parentPathParams);
-
-        String resourcePath = parentPath + createPath(node, pathParams) + "/";
-        _logger.debug("Adding path: [{}]", resourcePath);
-        api.setPath(resourcePath);
-        api.setOperations(operations(node, pathParams, addConfigApi));
-        apis.add(api);
-        if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) {
-            DataNodeContainer schemaNode = (DataNodeContainer) node;
-            Set<DataSchemaNode> dataSchemaNodes = schemaNode.getChildNodes();
-
-            for (DataSchemaNode childNode : dataSchemaNodes) {
-                addApis(childNode, apis, resourcePath, pathParams, addConfigApi);
-            }
-        }
-
-    }
-
-    private void addRpcs(final RpcDefinition rpcDefn, final List<Api> apis, final String parentPath) {
-        Api rpc = new Api();
-        String resourcePath = parentPath + rpcDefn.getQName().getLocalName();
-        rpc.setPath(resourcePath);
-
-        Operation operationSpec = new Operation();
-        operationSpec.setMethod("POST");
-        operationSpec.setNotes(rpcDefn.getDescription());
-        operationSpec.setNickname(rpcDefn.getQName().getLocalName());
-        rpc.setOperations(Arrays.asList(operationSpec));
-
-        apis.add(rpc);
-    }
-
-    /**
-     * @param node
-     * @param pathParams
-     * @return
-     */
-    private List<Operation> operations(final DataSchemaNode node, final List<Parameter> pathParams, final boolean isConfig) {
-        List<Operation> operations = new ArrayList<>();
-
-        OperationBuilder.Get getBuilder = new OperationBuilder.Get(node);
-        operations.add(getBuilder.pathParams(pathParams).build());
-
-        if (isConfig) {
-            OperationBuilder.Post postBuilder = new OperationBuilder.Post(node);
-            operations.add(postBuilder.pathParams(pathParams).build());
-
-            OperationBuilder.Put putBuilder = new OperationBuilder.Put(node);
-            operations.add(putBuilder.pathParams(pathParams).build());
-
-            OperationBuilder.Delete deleteBuilder = new OperationBuilder.Delete(node);
-            operations.add(deleteBuilder.pathParams(pathParams).build());
-        }
-        return operations;
-    }
-
-    private String createPath(final DataSchemaNode schemaNode, final List<Parameter> pathParams) {
-        ArrayList<LeafSchemaNode> pathListParams = new ArrayList<LeafSchemaNode>();
-        StringBuilder path = new StringBuilder();
-        QName _qName = schemaNode.getQName();
-        String localName = _qName.getLocalName();
-        path.append(localName);
-
-        if ((schemaNode instanceof ListSchemaNode)) {
-            final List<QName> listKeys = ((ListSchemaNode) schemaNode).getKeyDefinition();
-            for (final QName listKey : listKeys) {
-                {
-                    DataSchemaNode _dataChildByName = ((DataNodeContainer) schemaNode).getDataChildByName(listKey);
-                    pathListParams.add(((LeafSchemaNode) _dataChildByName));
-
-                    String pathParamIdentifier = new StringBuilder("/{").append(listKey.getLocalName()).append("}").toString();
-                    path.append(pathParamIdentifier);
-
-                    Parameter pathParam = new Parameter();
-                    pathParam.setName(listKey.getLocalName());
-                    pathParam.setDescription(_dataChildByName.getDescription());
-                    pathParam.setType("string");
-                    pathParam.setParamType("path");
-
-                    pathParams.add(pathParam);
-                }
-            }
-        }
-        return path.toString();
-    }
-
 }
index 241c8b84befd9390fc0bc97cd98c36bb0eb6c57f..c95f41c0bd1869567d8491eab0a533ae552bae8d 100644 (file)
  */
 package org.opendaylight.controller.sal.rest.doc.impl;
 
-import org.opendaylight.controller.sal.rest.doc.api.ApiDocService;
-import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
-import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import java.util.Map.Entry;
 
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
+import org.json.JSONWriter;
+import org.opendaylight.controller.sal.rest.doc.api.ApiDocService;
+import org.opendaylight.controller.sal.rest.doc.mountpoints.MountPointSwagger;
+import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
+import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
+
 /**
- * This service generates swagger
- * (See <a href="https://helloreverb.com/developers/swagger">https://helloreverb.com/developers/swagger</a>)
- * compliant documentation for RESTCONF APIs. The output of this is used by embedded Swagger UI.
+ * This service generates swagger (See <a
+ * href="https://helloreverb.com/developers/swagger"
+ * >https://helloreverb.com/developers/swagger</a>) compliant documentation for
+ * RESTCONF APIs. The output of this is used by embedded Swagger UI.
+ *
+ * NOTE: These API's need to be synchronized due to bug 1198. Thread access to
+ * the SchemaContext is not synchronized properly and thus you can end up with
+ * missing definitions without this synchronization. There are likely otherways
+ * to work around this limitation, but given that this API is a dev only tool
+ * and not dependent UI, this was the fastest work around.
+ *
  */
 public class ApiDocServiceImpl implements ApiDocService {
 
-  private static final ApiDocService INSTANCE = new ApiDocServiceImpl();
+    private static final ApiDocService INSTANCE = new ApiDocServiceImpl();
+
+    public static ApiDocService getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Generates index document for Swagger UI. This document lists out all
+     * modules with link to get APIs for each module. The API for each module is
+     * served by <code> getDocByModule()</code> method.
+     *
+     * @param uriInfo
+     * @return
+     */
+    @Override
+    public synchronized Response getRootDoc(UriInfo uriInfo) {
+        ApiDocGenerator generator = ApiDocGenerator.getInstance();
+        ResourceList rootDoc = generator.getResourceListing(uriInfo);
+
+        return Response.ok(rootDoc).build();
+    }
 
-  public static ApiDocService getInstance(){
-    return INSTANCE;
-  }
+    /**
+     * Generates Swagger compliant document listing APIs for module.
+     *
+     * @param module
+     * @param revision
+     * @param uriInfo
+     * @return
+     */
+    @Override
+    public synchronized Response getDocByModule(String module, String revision, UriInfo uriInfo) {
+        ApiDocGenerator generator = ApiDocGenerator.getInstance();
 
-  /**
-   * Generates index document for Swagger UI. This document lists out all modules with link to get APIs for
-   * each module. The API for each module is served by <code> getDocByModule()</code> method.
-   *
-   * @param uriInfo
-   * @return
-   */
-  @Override
-  public Response getRootDoc(UriInfo uriInfo) {
+        ApiDeclaration doc = generator.getApiDeclaration(module, revision, uriInfo);
+        return Response.ok(doc).build();
+    }
 
-    ApiDocGenerator generator = ApiDocGenerator.getInstance();
-    ResourceList rootDoc = generator.getResourceListing(uriInfo);
+    /**
+     * Redirects to embedded swagger ui.
+     *
+     * @param uriInfo
+     * @return
+     */
+    @Override
+    public synchronized Response getApiExplorer(UriInfo uriInfo) {
+        return Response
+                .seeOther(uriInfo.getBaseUriBuilder().path("../explorer/index.html").build())
+                .build();
+    }
 
-    return Response.ok(rootDoc).build();
-  }
+    @Override
+    public synchronized Response getListOfMounts(UriInfo uriInfo) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (OutputStreamWriter streamWriter = new OutputStreamWriter(baos)) {
+            JSONWriter writer = new JSONWriter(streamWriter);
+            writer.array();
+            for (Entry<String, Long> entry : MountPointSwagger.getInstance()
+                    .getInstanceIdentifiers().entrySet()) {
+                writer.object();
+                writer.key("instance").value(entry.getKey());
+                writer.key("id").value(entry.getValue());
+                writer.endObject();
+            }
+            writer.endArray();
+        } catch (Exception e) {
+            return Response.status(500).entity(e.getMessage()).build();
+        }
+        return Response.status(200).entity(baos.toString()).build();
+    }
 
-  /**
-   * Generates Swagger compliant document listing APIs for module.
-   *
-   * @param module
-   * @param revision
-   * @param uriInfo
-   * @return
-   */
-  @Override
-  public Response getDocByModule(String module, String revision, UriInfo uriInfo) {
-    ApiDocGenerator generator = ApiDocGenerator.getInstance();
+    @Override
+    public synchronized Response getMountRootDoc(String instanceNum, UriInfo uriInfo) {
+        ResourceList resourceList = MountPointSwagger.getInstance().getResourceList(uriInfo,
+                Long.parseLong(instanceNum));
+        return Response.ok(resourceList).build();
+    }
 
-    ApiDeclaration doc = generator.getApiDeclaration(module, revision, uriInfo);
-    return Response.ok(doc).build();
-  }
+    @Override
+    public synchronized Response getMountDocByModule(String instanceNum, String module,
+            String revision, UriInfo uriInfo) {
+        ApiDeclaration api = MountPointSwagger.getInstance().getMountPointApi(uriInfo,
+                Long.parseLong(instanceNum), module, revision);
+        return Response.ok(api).build();
+    }
 
-  /**
-   * Redirects to embedded swagger ui.
-   *
-   * @param uriInfo
-   * @return
-   */
-  @Override
-  public Response getApiExplorer(UriInfo uriInfo) {
-    return Response.seeOther(uriInfo.getBaseUriBuilder().path("../explorer/index.html").build()).build();
-  }
 }
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/BaseYangSwaggerGenerator.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/BaseYangSwaggerGenerator.java
new file mode 100644 (file)
index 0000000..68d31de
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.rest.doc.impl;
+
+import java.io.IOException;
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.ws.rs.core.UriInfo;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.opendaylight.controller.sal.rest.doc.model.builder.OperationBuilder;
+import org.opendaylight.controller.sal.rest.doc.swagger.Api;
+import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
+import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
+import org.opendaylight.controller.sal.rest.doc.swagger.Parameter;
+import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
+import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
+import com.google.common.base.Preconditions;
+
+public class BaseYangSwaggerGenerator {
+
+    private static Logger _logger = LoggerFactory.getLogger(BaseYangSwaggerGenerator.class);
+
+    protected static final String API_VERSION = "1.0.0";
+    protected static final String SWAGGER_VERSION = "1.2";
+    protected static final String RESTCONF_CONTEXT_ROOT = "restconf";
+    protected final DateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
+    private final ModelGenerator jsonConverter = new ModelGenerator();
+
+    // private Map<String, ApiDeclaration> MODULE_DOC_CACHE = new HashMap<>()
+    private final ObjectMapper mapper = new ObjectMapper();
+
+    protected BaseYangSwaggerGenerator() {
+        mapper.registerModule(new JsonOrgModule());
+        mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
+    }
+
+    /**
+     *
+     * @param uriInfo
+     * @param operType
+     * @return list of modules converted to swagger compliant resource list.
+     */
+    public ResourceList getResourceListing(UriInfo uriInfo, SchemaContext schemaContext,
+            String context) {
+
+        ResourceList resourceList = createResourceList();
+
+        Set<Module> modules = getSortedModules(schemaContext);
+
+        List<Resource> resources = new ArrayList<>(modules.size());
+
+        _logger.info("Modules found [{}]", modules.size());
+
+        for (Module module : modules) {
+            String revisionString = SIMPLE_DATE_FORMAT.format(module.getRevision());
+
+            Resource resource = new Resource();
+            _logger.debug("Working on [{},{}]...", module.getName(), revisionString);
+            ApiDeclaration doc = getApiDeclaration(module.getName(), revisionString, uriInfo,
+                    schemaContext, context);
+
+            if (doc != null) {
+                resource.setPath(generatePath(uriInfo, module.getName(), revisionString));
+                resources.add(resource);
+            } else {
+                _logger.debug("Could not generate doc for {},{}", module.getName(), revisionString);
+            }
+        }
+
+        resourceList.setApis(resources);
+
+        return resourceList;
+    }
+
+    protected ResourceList createResourceList() {
+        ResourceList resourceList = new ResourceList();
+        resourceList.setApiVersion(API_VERSION);
+        resourceList.setSwaggerVersion(SWAGGER_VERSION);
+        return resourceList;
+    }
+
+    protected String generatePath(UriInfo uriInfo, String name, String revision) {
+        URI uri = uriInfo.getRequestUriBuilder().path(generateCacheKey(name, revision)).build();
+        return uri.toASCIIString();
+    }
+
+    public ApiDeclaration getApiDeclaration(String module, String revision, UriInfo uriInfo,
+            SchemaContext schemaContext, String context) {
+        Date rev = null;
+        try {
+            rev = SIMPLE_DATE_FORMAT.parse(revision);
+        } catch (ParseException e) {
+            throw new IllegalArgumentException(e);
+        }
+        Module m = schemaContext.findModuleByName(module, rev);
+        Preconditions.checkArgument(m != null, "Could not find module by name,revision: " + module
+                + "," + revision);
+
+        return getApiDeclaration(m, rev, uriInfo, schemaContext, context);
+    }
+
+    public ApiDeclaration getApiDeclaration(Module module, Date revision, UriInfo uriInfo,
+            SchemaContext schemaContext, String context) {
+        String basePath = createBasePathFromUriInfo(uriInfo);
+
+        ApiDeclaration doc = getSwaggerDocSpec(module, basePath, context);
+        if (doc != null) {
+            return doc;
+        }
+        return null;
+    }
+
+    protected String createBasePathFromUriInfo(UriInfo uriInfo) {
+        String portPart = "";
+        int port = uriInfo.getBaseUri().getPort();
+        if (port != -1) {
+            portPart = ":" + port;
+        }
+        String basePath = new StringBuilder(uriInfo.getBaseUri().getScheme()).append("://")
+                .append(uriInfo.getBaseUri().getHost()).append(portPart).append("/")
+                .append(RESTCONF_CONTEXT_ROOT).toString();
+        return basePath;
+    }
+
+    public ApiDeclaration getSwaggerDocSpec(Module m, String basePath, String context) {
+        ApiDeclaration doc = createApiDeclaration(basePath);
+
+        List<Api> apis = new ArrayList<Api>();
+
+        Set<DataSchemaNode> dataSchemaNodes = m.getChildNodes();
+        _logger.debug("child nodes size [{}]", dataSchemaNodes.size());
+        for (DataSchemaNode node : dataSchemaNodes) {
+            if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) {
+
+                _logger.debug("Is Configuration node [{}] [{}]", node.isConfiguration(), node
+                        .getQName().getLocalName());
+
+                List<Parameter> pathParams = new ArrayList<Parameter>();
+                String resourcePath = getDataStorePath("/config/", context) + m.getName() + ":";
+                addApis(node, apis, resourcePath, pathParams, true);
+
+                pathParams = new ArrayList<Parameter>();
+                resourcePath = getDataStorePath("/operational/", context) + m.getName() + ":";
+                addApis(node, apis, resourcePath, pathParams, false);
+            }
+
+            Set<RpcDefinition> rpcs = m.getRpcs();
+            for (RpcDefinition rpcDefinition : rpcs) {
+                String resourcePath = getDataStorePath("/operations/", context) + m.getName() + ":";
+                addRpcs(rpcDefinition, apis, resourcePath);
+            }
+        }
+
+        _logger.debug("Number of APIs found [{}]", apis.size());
+
+        if (!apis.isEmpty()) {
+            doc.setApis(apis);
+            JSONObject models = null;
+
+            try {
+                models = jsonConverter.convertToJsonSchema(m);
+                doc.setModels(models);
+                if (_logger.isDebugEnabled()) {
+                    _logger.debug(mapper.writeValueAsString(doc));
+                }
+            } catch (IOException | JSONException e) {
+                e.printStackTrace();
+            }
+
+            return doc;
+        }
+        return null;
+    }
+
+    protected ApiDeclaration createApiDeclaration(String basePath) {
+        ApiDeclaration doc = new ApiDeclaration();
+        doc.setApiVersion(API_VERSION);
+        doc.setSwaggerVersion(SWAGGER_VERSION);
+        doc.setBasePath(basePath);
+        doc.setProduces(Arrays.asList("application/json", "application/xml"));
+        return doc;
+    }
+
+    protected String getDataStorePath(String dataStore, String context) {
+        return dataStore + context;
+    }
+
+    private String generateCacheKey(Module m) {
+        return generateCacheKey(m.getName(), SIMPLE_DATE_FORMAT.format(m.getRevision()));
+    }
+
+    private String generateCacheKey(String module, String revision) {
+        return module + "(" + revision + ")";
+    }
+
+    private void addApis(DataSchemaNode node, List<Api> apis, String parentPath,
+            List<Parameter> parentPathParams, boolean addConfigApi) {
+
+        Api api = new Api();
+        List<Parameter> pathParams = new ArrayList<Parameter>(parentPathParams);
+
+        String resourcePath = parentPath + createPath(node, pathParams) + "/";
+        _logger.debug("Adding path: [{}]", resourcePath);
+        api.setPath(resourcePath);
+        api.setOperations(operations(node, pathParams, addConfigApi));
+        apis.add(api);
+        if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) {
+            DataNodeContainer schemaNode = (DataNodeContainer) node;
+            Set<DataSchemaNode> dataSchemaNodes = schemaNode.getChildNodes();
+
+            for (DataSchemaNode childNode : dataSchemaNodes) {
+                // We don't support going to leaf nodes today. Only lists and
+                // containers.
+                if (childNode instanceof ListSchemaNode || childNode instanceof ContainerSchemaNode) {
+                    // keep config and operation attributes separate.
+                    if (childNode.isConfiguration() == addConfigApi) {
+                        addApis(childNode, apis, resourcePath, pathParams, addConfigApi);
+                    }
+                }
+            }
+        }
+
+    }
+
+    /**
+     * @param node
+     * @param pathParams
+     * @return
+     */
+    private List<Operation> operations(DataSchemaNode node, List<Parameter> pathParams,
+            boolean isConfig) {
+        List<Operation> operations = new ArrayList<>();
+
+        OperationBuilder.Get getBuilder = new OperationBuilder.Get(node, isConfig);
+        operations.add(getBuilder.pathParams(pathParams).build());
+
+        if (isConfig) {
+            OperationBuilder.Post postBuilder = new OperationBuilder.Post(node);
+            operations.add(postBuilder.pathParams(pathParams).build());
+
+            OperationBuilder.Put putBuilder = new OperationBuilder.Put(node);
+            operations.add(putBuilder.pathParams(pathParams).build());
+
+            OperationBuilder.Delete deleteBuilder = new OperationBuilder.Delete(node);
+            operations.add(deleteBuilder.pathParams(pathParams).build());
+        }
+        return operations;
+    }
+
+    private String createPath(final DataSchemaNode schemaNode, List<Parameter> pathParams) {
+        ArrayList<LeafSchemaNode> pathListParams = new ArrayList<LeafSchemaNode>();
+        StringBuilder path = new StringBuilder();
+        QName _qName = schemaNode.getQName();
+        String localName = _qName.getLocalName();
+        path.append(localName);
+
+        if ((schemaNode instanceof ListSchemaNode)) {
+            final List<QName> listKeys = ((ListSchemaNode) schemaNode).getKeyDefinition();
+            for (final QName listKey : listKeys) {
+                {
+                    DataSchemaNode _dataChildByName = ((DataNodeContainer) schemaNode)
+                            .getDataChildByName(listKey);
+                    pathListParams.add(((LeafSchemaNode) _dataChildByName));
+
+                    String pathParamIdentifier = new StringBuilder("/{")
+                            .append(listKey.getLocalName()).append("}").toString();
+                    path.append(pathParamIdentifier);
+
+                    Parameter pathParam = new Parameter();
+                    pathParam.setName(listKey.getLocalName());
+                    pathParam.setDescription(_dataChildByName.getDescription());
+                    pathParam.setType("string");
+                    pathParam.setParamType("path");
+
+                    pathParams.add(pathParam);
+                }
+            }
+        }
+        return path.toString();
+    }
+
+    protected void addRpcs(RpcDefinition rpcDefn, List<Api> apis, String parentPath) {
+        Api rpc = new Api();
+        String resourcePath = parentPath + rpcDefn.getQName().getLocalName();
+        rpc.setPath(resourcePath);
+
+        Operation operationSpec = new Operation();
+        operationSpec.setMethod("POST");
+        operationSpec.setNotes(rpcDefn.getDescription());
+        operationSpec.setNickname(rpcDefn.getQName().getLocalName());
+        if (rpcDefn.getOutput() != null) {
+            operationSpec.setType("(" + rpcDefn.getQName().getLocalName() + ")output");
+        }
+        if (rpcDefn.getInput() != null) {
+            Parameter payload = new Parameter();
+            payload.setParamType("body");
+            payload.setType("(" + rpcDefn.getQName().getLocalName() + ")input");
+            operationSpec.setParameters(Collections.singletonList(payload));
+        }
+
+        rpc.setOperations(Arrays.asList(operationSpec));
+
+        apis.add(rpc);
+    }
+
+    protected SortedSet<Module> getSortedModules(SchemaContext schemaContext) {
+        if (schemaContext == null) {
+            return new TreeSet<>();
+        }
+
+        Set<Module> modules = schemaContext.getModules();
+
+        SortedSet<Module> sortedModules = new TreeSet<>(new Comparator<Module>() {
+            @Override
+            public int compare(Module o1, Module o2) {
+                int result = o1.getName().compareTo(o2.getName());
+                if (result == 0) {
+                    result = o1.getRevision().compareTo(o2.getRevision());
+                }
+                if (result == 0) {
+                    result = o1.getNamespace().compareTo(o2.getNamespace());
+                }
+                return result;
+            }
+        });
+        for (Module m : modules) {
+            if (m != null) {
+                sortedModules.add(m);
+            }
+        }
+        return sortedModules;
+    }
+}
index 719dd78064fbee1815078866de80f2f90809ef85..0e929afc8461c5da04bafa6dc44e7c782f83417d 100644 (file)
@@ -18,6 +18,7 @@ import java.util.Set;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.opendaylight.controller.sal.rest.doc.model.builder.OperationBuilder;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
@@ -58,7 +59,7 @@ import org.slf4j.LoggerFactory;
  */
 public class ModelGenerator {
 
-    private static final Logger _logger = LoggerFactory.getLogger(ModelGenerator.class);
+    private static Logger _logger = LoggerFactory.getLogger(ModelGenerator.class);
 
     private static final String BASE_64 = "base64";
     private static final String BINARY_ENCODING_KEY = "binaryEncoding";
@@ -88,109 +89,123 @@ public class ModelGenerator {
     private static final Map<Class<? extends TypeDefinition<?>>, String> YANG_TYPE_TO_JSON_TYPE_MAPPING;
 
     static {
-        Map<Class<? extends TypeDefinition<?>>, String> tempMap1 = new HashMap<Class<? extends TypeDefinition<?>>, String>(10);
-        tempMap1.put(StringType.class , STRING);
-        tempMap1.put(BooleanType.class , BOOLEAN);
-        tempMap1.put(Int8.class , INTEGER);
-        tempMap1.put(Int16.class , INTEGER);
-        tempMap1.put(Int32.class , INTEGER);
-        tempMap1.put(Int64.class , INTEGER);
-        tempMap1.put(Uint16.class , INTEGER);
-        tempMap1.put(Uint32.class , INTEGER);
-        tempMap1.put(Uint64.class , INTEGER);
-        tempMap1.put(Uint8.class , INTEGER);
-        tempMap1.put(Decimal64.class , NUMBER);
-        tempMap1.put(EnumerationType.class , ENUM);
-        //TODO: Binary type
+        Map<Class<? extends TypeDefinition<?>>, String> tempMap1 = new HashMap<Class<? extends TypeDefinition<?>>, String>(
+                10);
+        tempMap1.put(StringType.class, STRING);
+        tempMap1.put(BooleanType.class, BOOLEAN);
+        tempMap1.put(Int8.class, INTEGER);
+        tempMap1.put(Int16.class, INTEGER);
+        tempMap1.put(Int32.class, INTEGER);
+        tempMap1.put(Int64.class, INTEGER);
+        tempMap1.put(Uint16.class, INTEGER);
+        tempMap1.put(Uint32.class, INTEGER);
+        tempMap1.put(Uint64.class, INTEGER);
+        tempMap1.put(Uint8.class, INTEGER);
+        tempMap1.put(Decimal64.class, NUMBER);
+        tempMap1.put(EnumerationType.class, ENUM);
+        // TODO: Binary type
 
         YANG_TYPE_TO_JSON_TYPE_MAPPING = Collections.unmodifiableMap(tempMap1);
     }
 
-    public ModelGenerator(){
+    public ModelGenerator() {
     }
 
-    public JSONObject convertToJsonSchema(final Module module) throws IOException, JSONException {
+    public JSONObject convertToJsonSchema(Module module) throws IOException, JSONException {
         JSONObject models = new JSONObject();
         processContainers(module, models);
         processRPCs(module, models);
-
         return models;
     }
 
-
-
-    private void processContainers(final Module module, final JSONObject models) throws IOException, JSONException {
+    private void processContainers(Module module, JSONObject models) throws IOException,
+            JSONException {
 
         String moduleName = module.getName();
-        Set<DataSchemaNode> childNodes =  module.getChildNodes();
+        Set<DataSchemaNode> childNodes = module.getChildNodes();
 
-        for(DataSchemaNode childNode : childNodes){
-            JSONObject moduleJSON=null;
-            String filename = childNode.getQName().getLocalName();
+        for (DataSchemaNode childNode : childNodes) {
+            JSONObject configModuleJSON = null;
+            JSONObject operationalModuleJSON = null;
+
+            String childNodeName = childNode.getQName().getLocalName();
             /*
              * For every container in the module
              */
-            if(childNode instanceof ContainerSchemaNode) {
-                moduleJSON = processContainer((ContainerSchemaNode)childNode, moduleName, true, models);
+            if (childNode instanceof ContainerSchemaNode) {
+                configModuleJSON = processContainer((ContainerSchemaNode) childNode, moduleName,
+                        true, models, true);
+                operationalModuleJSON = processContainer((ContainerSchemaNode) childNode,
+                        moduleName, true, models, false);
             }
 
-            if(moduleJSON!=null) {
-                _logger.debug("Adding model for [{}]", filename);
-                moduleJSON.put("id", filename);
-                models.put(filename, moduleJSON);
+            if (configModuleJSON != null) {
+                _logger.debug("Adding model for [{}]", OperationBuilder.CONFIG + childNodeName);
+                configModuleJSON.put("id", OperationBuilder.CONFIG + childNodeName);
+                models.put(OperationBuilder.CONFIG + childNodeName, configModuleJSON);
+            }
+            if (operationalModuleJSON != null) {
+                _logger.debug("Adding model for [{}]", OperationBuilder.OPERATIONAL + childNodeName);
+                operationalModuleJSON.put("id", OperationBuilder.OPERATIONAL + childNodeName);
+                models.put(OperationBuilder.OPERATIONAL + childNodeName, operationalModuleJSON);
             }
         }
 
     }
 
-
     /**
-     * Process the RPCs for a Module
-     * Spits out a file each of the name <rpcName>-input.json
-     * and <rpcName>-output.json for each RPC that contains
+     * Process the RPCs for a Module Spits out a file each of the name
+     * <rpcName>-input.json and <rpcName>-output.json for each RPC that contains
      * input & output elements
      *
      * @param module
      * @throws JSONException
      * @throws IOException
      */
-    private void processRPCs(final Module module, final JSONObject models) throws JSONException, IOException {
+    private void processRPCs(Module module, JSONObject models) throws JSONException, IOException {
 
-        Set<RpcDefinition> rpcs =  module.getRpcs();
+        Set<RpcDefinition> rpcs = module.getRpcs();
         String moduleName = module.getName();
-        for(RpcDefinition rpc: rpcs) {
+        for (RpcDefinition rpc : rpcs) {
 
             ContainerSchemaNode input = rpc.getInput();
-            if(input!=null) {
+            if (input != null) {
                 JSONObject inputJSON = processContainer(input, moduleName, true, models);
-                String filename = rpc.getQName().getLocalName() + "-input";
+                String filename = "(" + rpc.getQName().getLocalName() + ")input";
                 inputJSON.put("id", filename);
-                //writeToFile(filename, inputJSON.toString(2), moduleName);
+                // writeToFile(filename, inputJSON.toString(2), moduleName);
                 models.put(filename, inputJSON);
             }
 
             ContainerSchemaNode output = rpc.getOutput();
-            if(output!=null) {
+            if (output != null) {
                 JSONObject outputJSON = processContainer(output, moduleName, true, models);
-                String filename = rpc.getQName().getLocalName() + "-output";
+                String filename = "(" + rpc.getQName().getLocalName() + ")output";
                 outputJSON.put("id", filename);
                 models.put(filename, outputJSON);
             }
         }
     }
 
-
     /**
      * Processes the container node and populates the moduleJSON
      *
      * @param container
      * @param moduleName
+     * @param isConfig
      * @throws JSONException
      * @throws IOException
      */
-    private JSONObject processContainer(final ContainerSchemaNode container, final String moduleName, final boolean addSchemaStmt, final JSONObject models) throws JSONException, IOException{
+    private JSONObject processContainer(ContainerSchemaNode container, String moduleName,
+            boolean addSchemaStmt, JSONObject models) throws JSONException, IOException {
+        return processContainer(container, moduleName, addSchemaStmt, models, (Boolean) null);
+    }
+
+    private JSONObject processContainer(ContainerSchemaNode container, String moduleName,
+            boolean addSchemaStmt, JSONObject models, Boolean isConfig) throws JSONException,
+            IOException {
         JSONObject moduleJSON = getSchemaTemplate();
-        if(addSchemaStmt) {
+        if (addSchemaStmt) {
             moduleJSON = getSchemaTemplate();
         } else {
             moduleJSON = new JSONObject();
@@ -201,49 +216,62 @@ public class ModelGenerator {
         moduleJSON.put(DESCRIPTION_KEY, containerDescription);
 
         Set<DataSchemaNode> containerChildren = container.getChildNodes();
-        JSONObject properties = processChildren(containerChildren, moduleName, models);
+        JSONObject properties = processChildren(containerChildren, moduleName, models, isConfig);
         moduleJSON.put(PROPERTIES_KEY, properties);
         return moduleJSON;
     }
 
+    private JSONObject processChildren(Set<DataSchemaNode> nodes, String moduleName,
+            JSONObject models) throws JSONException, IOException {
+        return processChildren(nodes, moduleName, models, null);
+    }
+
     /**
      * Processes the nodes
+     *
      * @param nodes
      * @param moduleName
+     * @param isConfig
      * @return
      * @throws JSONException
      * @throws IOException
      */
-    private JSONObject processChildren(final Set<DataSchemaNode> nodes, final String moduleName, final JSONObject models) throws JSONException, IOException {
+    private JSONObject processChildren(Set<DataSchemaNode> nodes, String moduleName,
+            JSONObject models, Boolean isConfig) throws JSONException, IOException {
 
         JSONObject properties = new JSONObject();
 
-        for(DataSchemaNode node : nodes){
-            String name = node.getQName().getLocalName();
-            JSONObject property = null;
-            if(node instanceof LeafSchemaNode) {
-                property = processLeafNode((LeafSchemaNode)node);
-            } else if (node instanceof ListSchemaNode) {
-                property = processListSchemaNode((ListSchemaNode)node, moduleName, models);
+        for (DataSchemaNode node : nodes) {
+            if (isConfig == null || node.isConfiguration() == isConfig) {
 
-            } else if (node instanceof LeafListSchemaNode) {
-                property = processLeafListNode((LeafListSchemaNode)node);
+                String name = node.getQName().getLocalName();
+                JSONObject property = null;
+                if (node instanceof LeafSchemaNode) {
+                    property = processLeafNode((LeafSchemaNode) node);
+                } else if (node instanceof ListSchemaNode) {
+                    property = processListSchemaNode((ListSchemaNode) node, moduleName, models);
 
-            } else if (node instanceof ChoiceNode) {
-                property = processChoiceNode((ChoiceNode)node, moduleName, models);
+                } else if (node instanceof LeafListSchemaNode) {
+                    property = processLeafListNode((LeafListSchemaNode) node);
 
-            } else if (node instanceof AnyXmlSchemaNode) {
-                property = processAnyXMLNode((AnyXmlSchemaNode)node);
+                } else if (node instanceof ChoiceNode) {
+                    property = processChoiceNode((ChoiceNode) node, moduleName, models);
 
-            } else if (node instanceof ContainerSchemaNode) {
-                property = processContainer((ContainerSchemaNode)node, moduleName, false, models);
+                } else if (node instanceof AnyXmlSchemaNode) {
+                    property = processAnyXMLNode((AnyXmlSchemaNode) node);
 
-            } else {
-                throw new IllegalArgumentException("Unknown DataSchemaNode type: " + node.getClass());
-            }
+                } else if (node instanceof ContainerSchemaNode) {
+                    property = processContainer((ContainerSchemaNode) node, moduleName, false,
+                            models, isConfig);
+
+                } else {
+                    throw new IllegalArgumentException("Unknown DataSchemaNode type: "
+                            + node.getClass());
+                }
 
-            property.putOpt(DESCRIPTION_KEY, node.getDescription());
-            properties.put(name, property);
+                property.putOpt(DESCRIPTION_KEY, node.getDescription());
+                properties.put(name, property);
+            }
         }
         return properties;
     }
@@ -253,7 +281,7 @@ public class ModelGenerator {
      * @param listNode
      * @throws JSONException
      */
-    private JSONObject processLeafListNode(final LeafListSchemaNode listNode) throws JSONException {
+    private JSONObject processLeafListNode(LeafListSchemaNode listNode) throws JSONException {
         JSONObject props = new JSONObject();
         props.put(TYPE_KEY, ARRAY_TYPE);
 
@@ -274,12 +302,13 @@ public class ModelGenerator {
      * @throws JSONException
      * @throws IOException
      */
-    private JSONObject processChoiceNode(final ChoiceNode choiceNode, final String moduleName, final JSONObject models) throws JSONException, IOException {
+    private JSONObject processChoiceNode(ChoiceNode choiceNode, String moduleName, JSONObject models)
+            throws JSONException, IOException {
 
         Set<ChoiceCaseNode> cases = choiceNode.getCases();
 
         JSONArray choiceProps = new JSONArray();
-        for(ChoiceCaseNode choiceCase: cases) {
+        for (ChoiceCaseNode choiceCase : cases) {
             String choiceName = choiceCase.getQName().getLocalName();
             JSONObject choiceProp = processChildren(choiceCase.getChildNodes(), moduleName, models);
             JSONObject choiceObj = new JSONObject();
@@ -295,23 +324,23 @@ public class ModelGenerator {
         return oneOfProps;
     }
 
-
     /**
      *
      * @param constraints
      * @param props
      * @throws JSONException
      */
-    private void processConstraints(final ConstraintDefinition constraints, final JSONObject props) throws JSONException {
+    private void processConstraints(ConstraintDefinition constraints, JSONObject props)
+            throws JSONException {
         boolean isMandatory = constraints.isMandatory();
         props.put(REQUIRED_KEY, isMandatory);
 
         Integer minElements = constraints.getMinElements();
         Integer maxElements = constraints.getMaxElements();
-        if(minElements !=null) {
+        if (minElements != null) {
             props.put(MIN_ITEMS, minElements);
         }
-        if(maxElements !=null) {
+        if (maxElements != null) {
             props.put(MAX_ITEMS, maxElements);
         }
     }
@@ -319,9 +348,9 @@ public class ModelGenerator {
     /**
      * Parses a ListSchema node.
      *
-     * Due to a limitation of the RAML--->JAX-RS tool, sub-properties
-     * must be in a separate JSON schema file. Hence, we have to write
-     * some properties to a new file, while continuing to process the rest.
+     * Due to a limitation of the RAML--->JAX-RS tool, sub-properties must be in
+     * a separate JSON schema file. Hence, we have to write some properties to a
+     * new file, while continuing to process the rest.
      *
      * @param listNode
      * @param moduleName
@@ -329,7 +358,8 @@ public class ModelGenerator {
      * @throws JSONException
      * @throws IOException
      */
-    private JSONObject processListSchemaNode(final ListSchemaNode listNode, final String moduleName, final JSONObject models) throws JSONException, IOException {
+    private JSONObject processListSchemaNode(ListSchemaNode listNode, String moduleName,
+            JSONObject models) throws JSONException, IOException {
 
         Set<DataSchemaNode> listChildren = listNode.getChildNodes();
         String fileName = listNode.getQName().getLocalName();
@@ -340,20 +370,19 @@ public class ModelGenerator {
         childSchema.put(PROPERTIES_KEY, childSchemaProperties);
 
         /*
-         * Due to a limitation of the RAML--->JAX-RS tool, sub-properties
-         * must be in a separate JSON schema file. Hence, we have to write
-         * some properties to a new file, while continuing to process the rest.
+         * Due to a limitation of the RAML--->JAX-RS tool, sub-properties must
+         * be in a separate JSON schema file. Hence, we have to write some
+         * properties to a new file, while continuing to process the rest.
          */
-        //writeToFile(fileName, childSchema.toString(2), moduleName);
+        // writeToFile(fileName, childSchema.toString(2), moduleName);
         childSchema.put("id", fileName);
         models.put(fileName, childSchema);
 
-
         JSONObject listNodeProperties = new JSONObject();
         listNodeProperties.put(TYPE_KEY, ARRAY_TYPE);
 
         JSONObject items = new JSONObject();
-        items.put(REF_KEY,fileName );
+        items.put(REF_KEY, fileName);
         listNodeProperties.put(ITEMS_KEY, items);
 
         return listNodeProperties;
@@ -366,7 +395,7 @@ public class ModelGenerator {
      * @return
      * @throws JSONException
      */
-    private JSONObject processLeafNode(final LeafSchemaNode leafNode) throws JSONException {
+    private JSONObject processLeafNode(LeafSchemaNode leafNode) throws JSONException {
         JSONObject property = new JSONObject();
 
         String leafDescription = leafNode.getDescription();
@@ -384,7 +413,7 @@ public class ModelGenerator {
      * @return
      * @throws JSONException
      */
-    private JSONObject processAnyXMLNode(final AnyXmlSchemaNode leafNode) throws JSONException {
+    private JSONObject processAnyXMLNode(AnyXmlSchemaNode leafNode) throws JSONException {
         JSONObject property = new JSONObject();
 
         String leafDescription = leafNode.getDescription();
@@ -399,27 +428,28 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processTypeDef(final TypeDefinition<?> leafTypeDef, final JSONObject property) throws JSONException {
+    private void processTypeDef(TypeDefinition<?> leafTypeDef, JSONObject property)
+            throws JSONException {
 
-        if(leafTypeDef instanceof ExtendedType){
+        if (leafTypeDef instanceof ExtendedType) {
             processExtendedType(leafTypeDef, property);
         } else if (leafTypeDef instanceof EnumerationType) {
-            processEnumType((EnumerationType)leafTypeDef, property);
+            processEnumType((EnumerationType) leafTypeDef, property);
 
         } else if (leafTypeDef instanceof BitsTypeDefinition) {
-            processBitsType((BitsTypeDefinition)leafTypeDef, property);
+            processBitsType((BitsTypeDefinition) leafTypeDef, property);
 
         } else if (leafTypeDef instanceof UnionTypeDefinition) {
-            processUnionType((UnionTypeDefinition)leafTypeDef, property);
+            processUnionType((UnionTypeDefinition) leafTypeDef, property);
 
         } else if (leafTypeDef instanceof IdentityrefTypeDefinition) {
             property.putOpt(TYPE_KEY, "object");
         } else if (leafTypeDef instanceof BinaryTypeDefinition) {
-            processBinaryType((BinaryTypeDefinition)leafTypeDef, property);
+            processBinaryType((BinaryTypeDefinition) leafTypeDef, property);
         } else {
-            //System.out.println("In else: " + leafTypeDef.getClass());
+            // System.out.println("In else: " + leafTypeDef.getClass());
             String jsonType = YANG_TYPE_TO_JSON_TYPE_MAPPING.get(leafTypeDef.getClass());
-            if(jsonType==null) {
+            if (jsonType == null) {
                 jsonType = "object";
             }
             property.putOpt(TYPE_KEY, jsonType);
@@ -432,29 +462,32 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processExtendedType(final TypeDefinition<?> leafTypeDef, final JSONObject property) throws JSONException {
+    private void processExtendedType(TypeDefinition<?> leafTypeDef, JSONObject property)
+            throws JSONException {
         Object leafBaseType = leafTypeDef.getBaseType();
-        if(leafBaseType instanceof ExtendedType){
-            //recursively process an extended type until we hit a base type
-            processExtendedType((TypeDefinition<?>)leafBaseType, property);
+        if (leafBaseType instanceof ExtendedType) {
+            // recursively process an extended type until we hit a base type
+            processExtendedType((TypeDefinition<?>) leafBaseType, property);
         } else {
-            List<LengthConstraint> lengthConstraints = ((ExtendedType) leafTypeDef).getLengthConstraints();
-            for(LengthConstraint lengthConstraint: lengthConstraints) {
+            List<LengthConstraint> lengthConstraints = ((ExtendedType) leafTypeDef)
+                    .getLengthConstraints();
+            for (LengthConstraint lengthConstraint : lengthConstraints) {
                 Number min = lengthConstraint.getMin();
                 Number max = lengthConstraint.getMax();
                 property.putOpt(MIN_LENGTH_KEY, min);
                 property.putOpt(MAX_LENGTH_KEY, max);
             }
             String jsonType = YANG_TYPE_TO_JSON_TYPE_MAPPING.get(leafBaseType.getClass());
-            property.putOpt(TYPE_KEY,jsonType );
+            property.putOpt(TYPE_KEY, jsonType);
         }
 
     }
 
     /*
-     *
-     */
-    private void processBinaryType(final BinaryTypeDefinition binaryType, final JSONObject property) throws JSONException {
+   *
+   */
+    private void processBinaryType(BinaryTypeDefinition binaryType, JSONObject property)
+            throws JSONException {
         property.put(TYPE_KEY, STRING);
         JSONObject media = new JSONObject();
         media.put(BINARY_ENCODING_KEY, BASE_64);
@@ -467,10 +500,11 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processEnumType(final EnumerationType enumLeafType, final JSONObject property) throws JSONException {
+    private void processEnumType(EnumerationType enumLeafType, JSONObject property)
+            throws JSONException {
         List<EnumPair> enumPairs = enumLeafType.getValues();
         List<String> enumNames = new ArrayList<String>();
-        for(EnumPair enumPair: enumPairs) {
+        for (EnumPair enumPair : enumPairs) {
             enumNames.add(enumPair.getName());
         }
         property.putOpt(ENUM, new JSONArray(enumNames));
@@ -482,14 +516,15 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processBitsType(final BitsTypeDefinition bitsType, final JSONObject property) throws JSONException{
+    private void processBitsType(BitsTypeDefinition bitsType, JSONObject property)
+            throws JSONException {
         property.put(TYPE_KEY, ARRAY_TYPE);
         property.put(MIN_ITEMS, 0);
         property.put(UNIQUE_ITEMS_KEY, true);
         JSONArray enumValues = new JSONArray();
 
         List<Bit> bits = bitsType.getBits();
-        for(Bit bit: bits) {
+        for (Bit bit : bits) {
             enumValues.put(bit.getName());
         }
         JSONObject itemsValue = new JSONObject();
@@ -497,27 +532,26 @@ public class ModelGenerator {
         property.put(ITEMS_KEY, itemsValue);
     }
 
-
     /**
      *
      * @param unionType
      * @param property
      * @throws JSONException
      */
-    private void processUnionType(final UnionTypeDefinition unionType, final JSONObject property) throws JSONException{
+    private void processUnionType(UnionTypeDefinition unionType, JSONObject property)
+            throws JSONException {
 
         List<TypeDefinition<?>> unionTypes = unionType.getTypes();
         JSONArray unionArray = new JSONArray();
-        for(TypeDefinition<?> typeDef: unionTypes) {
+        for (TypeDefinition<?> typeDef : unionTypes) {
             unionArray.put(YANG_TYPE_TO_JSON_TYPE_MAPPING.get(typeDef.getClass()));
         }
         property.put(TYPE_KEY, unionArray);
     }
 
-
     /**
-     * Helper method to generate a pre-filled
-     * JSON schema object.
+     * Helper method to generate a pre-filled JSON schema object.
+     *
      * @return
      * @throws JSONException
      */
index bec34b232a4b7d919cc996577fe81d17c0d05bf7..e833c613997a143a7384c7ac336029498504e254 100644 (file)
@@ -7,18 +7,19 @@
  */
 package org.opendaylight.controller.sal.rest.doc.jaxrs;
 
-import org.opendaylight.controller.sal.rest.doc.impl.ApiDocServiceImpl;
-
-import javax.ws.rs.core.Application;
 import java.util.HashSet;
 import java.util.Set;
 
+import javax.ws.rs.core.Application;
+
+import org.opendaylight.controller.sal.rest.doc.impl.ApiDocServiceImpl;
+
 public class ApiDocApplication extends Application {
-  @Override
-  public Set<Object> getSingletons() {
-    Set<Object> singletons = new HashSet<>();
-    singletons.add(ApiDocServiceImpl.getInstance());
-    singletons.add(new JaxbContextResolver());
-    return singletons;
-  }
+    @Override
+    public Set<Object> getSingletons() {
+        Set<Object> singletons = new HashSet<>();
+        singletons.add(ApiDocServiceImpl.getInstance());
+        singletons.add(new JaxbContextResolver());
+        return singletons;
+    }
 }
index 5508507d5faf57ebb468795e78cad61f98595711..66fc80fdc7b97f9f780453282d03a3ef4dbb983e 100644 (file)
@@ -7,37 +7,39 @@
  */
 package org.opendaylight.controller.sal.rest.doc.jaxrs;
 
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
-import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
-
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.ext.ContextResolver;
 import javax.ws.rs.ext.Provider;
 
+import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
+
 @Provider
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 public class JaxbContextResolver implements ContextResolver<ObjectMapper> {
 
-  private ObjectMapper ctx;
+    private final ObjectMapper ctx;
 
-  public JaxbContextResolver(){
-    ctx = new ObjectMapper();
-    ctx.registerModule(new JsonOrgModule());
-    ctx.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.ALWAYS);
-  }
+    public JaxbContextResolver() {
+        ctx = new ObjectMapper();
+        ctx.registerModule(new JsonOrgModule());
+        ctx.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.ALWAYS);
+    }
 
-  @Override
-  public ObjectMapper getContext(Class<?> aClass) {
+    @Override
+    public ObjectMapper getContext(Class<?> aClass) {
 
-    if (ApiDeclaration.class.isAssignableFrom(aClass)){
-      return ctx;
-    }
+        if (ApiDeclaration.class.isAssignableFrom(aClass)) {
+            return ctx;
+        }
 
-    return null;//must return null so that jax-rs can continue context search
-  }
+        return null;// must return null so that jax-rs can continue context
+                    // search
+    }
 }
index fc890d5a2d53de69cf06aa7de91295e369685dc5..9a33ee31b371cb99febb084da4198f83e74fa97c 100644 (file)
  */
 package org.opendaylight.controller.sal.rest.doc.model.builder;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
 import org.opendaylight.controller.sal.rest.doc.swagger.Parameter;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  *
  */
 public final class OperationBuilder {
 
-  /**
+    public static final String OPERATIONAL = "(operational)";
+    public static final String CONFIG = "(config)";
+
+    /**
    *
    */
-  public static class Get{
-
-    protected Operation spec;
-    protected DataSchemaNode schemaNode;
-    private final String METHOD_NAME = "GET";
-
-    public Get(DataSchemaNode node){
-      this.schemaNode = node;
-      spec = new Operation();
-      spec.setMethod(METHOD_NAME);
-      spec.setNickname(METHOD_NAME + "-" + node.getQName().getLocalName());
-      spec.setType(node.getQName().getLocalName());
-      spec.setNotes(node.getDescription());
+    public static class Get {
+
+        protected Operation spec;
+        protected DataSchemaNode schemaNode;
+        private final String METHOD_NAME = "GET";
+
+        public Get(DataSchemaNode node, boolean isConfig) {
+            this.schemaNode = node;
+            spec = new Operation();
+            spec.setMethod(METHOD_NAME);
+            spec.setNickname(METHOD_NAME + "-" + node.getQName().getLocalName());
+            spec.setType((isConfig ? CONFIG : OPERATIONAL) + node.getQName().getLocalName());
+            spec.setNotes(node.getDescription());
+        }
+
+        public Get pathParams(List<Parameter> params) {
+            List<Parameter> pathParameters = new ArrayList<>(params);
+            spec.setParameters(pathParameters);
+            return this;
+        }
+
+        public Operation build() {
+            return spec;
+        }
     }
 
-    public Get pathParams(List<Parameter> params){
-      List<Parameter> pathParameters = new ArrayList<>(params);
-      spec.setParameters(pathParameters);
-      return this;
-    }
-
-    public Operation build(){
-      return spec;
-    }
-  }
-
-  /**
+    /**
    *
    */
-  public static class Put{
-    protected Operation spec;
-    protected DataSchemaNode schemaNode;
-    private final String METHOD_NAME = "PUT";
-
-    public Put(DataSchemaNode node){
-      this.schemaNode = node;
-      spec = new Operation();
-      spec.setType(node.getQName().getLocalName());
-      spec.setNotes(node.getDescription());
-    }
-
-    public Put pathParams(List<Parameter> params){
-      List<Parameter> parameters = new ArrayList<>(params);
-      Parameter payload = new Parameter();
-      payload.setParamType("body");
-      payload.setType(schemaNode.getQName().getLocalName());
-      parameters.add(payload);
-      spec.setParameters(parameters);
-      return this;
-    }
-
-    public Operation build(){
-      spec.setMethod(METHOD_NAME);
-      spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName());
-      return spec;
+    public static class Put {
+        protected Operation spec;
+        protected DataSchemaNode schemaNode;
+        private final String METHOD_NAME = "PUT";
+
+        public Put(DataSchemaNode node) {
+            this.schemaNode = node;
+            spec = new Operation();
+            spec.setType(CONFIG + node.getQName().getLocalName());
+            spec.setNotes(node.getDescription());
+        }
+
+        public Put pathParams(List<Parameter> params) {
+            List<Parameter> parameters = new ArrayList<>(params);
+            Parameter payload = new Parameter();
+            payload.setParamType("body");
+            payload.setType(CONFIG + schemaNode.getQName().getLocalName());
+            parameters.add(payload);
+            spec.setParameters(parameters);
+            return this;
+        }
+
+        public Operation build() {
+            spec.setMethod(METHOD_NAME);
+            spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName());
+            return spec;
+        }
     }
-  }
 
-  /**
+    /**
    *
    */
-  public static final class Post extends Put{
+    public static final class Post extends Put {
 
-    private final String METHOD_NAME = "POST";
+        private final String METHOD_NAME = "POST";
 
-    public Post(DataSchemaNode node){
-      super(node);
-    }
+        public Post(DataSchemaNode node) {
+            super(node);
+        }
 
-    public Operation build(){
-      spec.setMethod(METHOD_NAME);
-      spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName());
-      return spec;
+        @Override
+        public Operation build() {
+            spec.setMethod(METHOD_NAME);
+            spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName());
+            return spec;
+        }
     }
-  }
 
-  /**
+    /**
    *
    */
-  public static final class Delete extends Get {
-    private final String METHOD_NAME = "DELETE";
-
-    public Delete(DataSchemaNode node){
-      super(node);
-    }
-
-    public Operation build(){
-      spec.setMethod(METHOD_NAME);
-      spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName());
-      spec.setType(null);
-      return spec;
+    public static final class Delete extends Get {
+        private final String METHOD_NAME = "DELETE";
+
+        public Delete(DataSchemaNode node) {
+            super(node, false);
+        }
+
+        @Override
+        public Operation build() {
+            spec.setMethod(METHOD_NAME);
+            spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName());
+            spec.setType(null);
+            return spec;
+        }
     }
-  }
 }
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/mountpoints/MountPointSwagger.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/mountpoints/MountPointSwagger.java
new file mode 100644 (file)
index 0000000..b996bf1
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.rest.doc.mountpoints;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.ws.rs.core.UriInfo;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService.MountProvisionListener;
+import org.opendaylight.controller.sal.rest.doc.impl.BaseYangSwaggerGenerator;
+import org.opendaylight.controller.sal.rest.doc.swagger.Api;
+import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
+import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
+import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
+import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class MountPointSwagger extends BaseYangSwaggerGenerator implements MountProvisionListener {
+
+    private static final String DATASTORES_REVISION = "-";
+    private static final String DATASTORES_LABEL = "Datastores";
+
+    private MountProvisionService mountService;
+    private final Map<InstanceIdentifier, Long> instanceIdToLongId = new TreeMap<>(
+            new Comparator<InstanceIdentifier>() {
+                @Override
+                public int compare(InstanceIdentifier o1, InstanceIdentifier o2) {
+                    return o1.toString().compareToIgnoreCase(o2.toString());
+                }
+            });
+    private final Map<Long, InstanceIdentifier> longIdToInstanceId = new HashMap<>();
+    private final Object lock = new Object();
+
+    private final AtomicLong idKey = new AtomicLong(0);
+
+    private static AtomicReference<MountPointSwagger> selfRef = new AtomicReference<>();
+    private SchemaService globalSchema;
+
+    public Map<String, Long> getInstanceIdentifiers() {
+        Map<String, Long> urlToId = new HashMap<>();
+        synchronized (lock) {
+            SchemaContext context = globalSchema.getGlobalContext();
+            for (Entry<InstanceIdentifier, Long> entry : instanceIdToLongId.entrySet()) {
+                String modName = findModuleName(entry.getKey(), context);
+                urlToId.put(generateUrlPrefixFromInstanceID(entry.getKey(), modName),
+                        entry.getValue());
+            }
+        }
+        return urlToId;
+    }
+
+    public void setGlobalSchema(SchemaService globalSchema) {
+        this.globalSchema = globalSchema;
+    }
+
+    private String findModuleName(InstanceIdentifier id, SchemaContext context) {
+        PathArgument rootQName = id.getPath().get(0);
+        for (Module mod : context.getModules()) {
+            if (mod.getDataChildByName(rootQName.getNodeType()) != null) {
+                return mod.getName();
+            }
+        }
+        return null;
+    }
+
+    private String generateUrlPrefixFromInstanceID(InstanceIdentifier key, String moduleName) {
+        List<PathArgument> path = key.getPath();
+        StringBuilder builder = new StringBuilder();
+        if (moduleName != null) {
+            builder.append(moduleName);
+            builder.append(":");
+        }
+        boolean first = true;
+        for (PathArgument arg : path) {
+
+            String name = arg.getNodeType().getLocalName();
+            if (first) {
+                first = false;
+            } else {
+                builder.append("/");
+            }
+            builder.append(name);
+            if (arg instanceof InstanceIdentifier.NodeIdentifierWithPredicates) {
+                NodeIdentifierWithPredicates nodeId = (NodeIdentifierWithPredicates) arg;
+                for (Entry<QName, Object> entry : nodeId.getKeyValues().entrySet()) {
+                    builder.append("/").append(entry.getValue());
+                }
+            }
+        }
+
+        return builder.append("/").toString();
+    }
+
+    private String getYangMountUrl(InstanceIdentifier key) {
+        String modName = findModuleName(key, globalSchema.getGlobalContext());
+        return generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount/";
+    }
+
+    public ResourceList getResourceList(UriInfo uriInfo, Long id) {
+        InstanceIdentifier iid = getInstanceId(id);
+        if (iid == null) {
+            return null; // indicating not found.
+        }
+        SchemaContext context = getSchemaContext(iid);
+        String urlPrefix = getYangMountUrl(iid);
+        if (context == null) {
+            return createResourceList();
+        }
+        List<Resource> resources = new LinkedList<>();
+        Resource dataStores = new Resource();
+        dataStores.setDescription("Provides methods for accessing the data stores.");
+        dataStores.setPath(generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION));
+        resources.add(dataStores);
+        ResourceList list = super.getResourceListing(uriInfo, context, urlPrefix);
+        resources.addAll(list.getApis());
+        list.setApis(resources);
+        return list;
+    }
+
+    private InstanceIdentifier getInstanceId(Long id) {
+        InstanceIdentifier instanceId;
+        synchronized (lock) {
+            instanceId = longIdToInstanceId.get(id);
+        }
+        return instanceId;
+    }
+
+    private SchemaContext getSchemaContext(InstanceIdentifier id) {
+
+        if (id == null) {
+            return null;
+        }
+
+        MountProvisionInstance mountPoint = mountService.getMountPoint(id);
+        if (mountPoint == null) {
+            return null;
+        }
+
+        SchemaContext context = mountPoint.getSchemaContext();
+        if (context == null) {
+            return null;
+        }
+        return context;
+    }
+
+    public ApiDeclaration getMountPointApi(UriInfo uriInfo, Long id, String module, String revision) {
+        InstanceIdentifier iid = getInstanceId(id);
+        SchemaContext context = getSchemaContext(iid);
+        String urlPrefix = getYangMountUrl(iid);
+        if (context == null) {
+            return null;
+        }
+
+        if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) {
+            return generateDataStoreApiDoc(uriInfo, urlPrefix);
+        }
+        return super.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
+    }
+
+    private ApiDeclaration generateDataStoreApiDoc(UriInfo uriInfo, String context) {
+
+        ApiDeclaration declaration = super.createApiDeclaration(createBasePathFromUriInfo(uriInfo));
+        List<Api> apis = new LinkedList<>();
+        apis.add(createGetApi("config",
+                "Queries the config (startup) datastore on the mounted hosted.", context));
+        apis.add(createGetApi("operational",
+                "Queries the operational (running) datastore on the mounted hosted.", context));
+        apis.add(createGetApi("operations",
+                "Queries the available operations (RPC calls) on the mounted hosted.", context));
+        declaration.setApis(apis);
+        return declaration;
+
+    }
+
+    private Api createGetApi(String datastore, String note, String context) {
+        Operation getConfig = new Operation();
+        getConfig.setMethod("GET");
+        getConfig.setNickname("GET " + datastore);
+        getConfig.setNotes(note);
+
+        Api api = new Api();
+        api.setPath(getDataStorePath("/" + datastore + "/", context));
+        api.setOperations(Collections.singletonList(getConfig));
+
+        return api;
+    }
+
+    public void setMountService(MountProvisionService mountService) {
+        this.mountService = mountService;
+    }
+
+    @Override
+    public void onMountPointCreated(InstanceIdentifier path) {
+        synchronized (lock) {
+            Long idLong = idKey.incrementAndGet();
+            instanceIdToLongId.put(path, idLong);
+            longIdToInstanceId.put(idLong, path);
+        }
+    }
+
+    @Override
+    public void onMountPointRemoved(InstanceIdentifier path) {
+        synchronized (lock) {
+            Long id = instanceIdToLongId.remove(path);
+            longIdToInstanceId.remove(id);
+        }
+    }
+
+    public static MountPointSwagger getInstance() {
+        MountPointSwagger swagger = selfRef.get();
+        if (swagger == null) {
+            selfRef.compareAndSet(null, new MountPointSwagger());
+            swagger = selfRef.get();
+        }
+        return swagger;
+    }
+
+}
index a2be741c744a561ff49c20901f1f23b0cd9721b2..cc45875dfbed9c39b9e85d1dc73865fc594fa05b 100644 (file)
@@ -10,28 +10,29 @@ package org.opendaylight.controller.sal.rest.doc.swagger;
 import java.util.List;
 
 /**
- * Implementation of swagger spec
- * (see <a href="https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#522-api-object">
- *   https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#522-api-object</a>)
+ * Implementation of swagger spec (see <a href=
+ * "https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#522-api-object"
+ * > https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#522-api
+ * -object</a>)
  */
 public class Api {
 
-  private String path;
-  private List<Operation> operations;
+    private String path;
+    private List<Operation> operations;
 
-  public String getPath() {
-    return path;
-  }
+    public String getPath() {
+        return path;
+    }
 
-  public void setPath(String path) {
-    this.path = path;
-  }
+    public void setPath(String path) {
+        this.path = path;
+    }
 
-  public List<Operation> getOperations() {
-    return operations;
-  }
+    public List<Operation> getOperations() {
+        return operations;
+    }
 
-  public void setOperations(List<Operation> operations) {
-    this.operations = operations;
-  }
+    public void setOperations(List<Operation> operations) {
+        this.operations = operations;
+    }
 }
index e89bdaf603ede02cd0b22d7e06b3072b91a58ef4..4ba0ab2255a7d9184af5bfe1f949716ff9141d31 100644 (file)
@@ -7,85 +7,86 @@
  */
 package org.opendaylight.controller.sal.rest.doc.swagger;
 
-import org.json.JSONObject;
-
 import java.util.List;
 
+import org.json.JSONObject;
+
 /**
- * Implementation of swagger spec
- * (see <a href="https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#52-api-declaration">
- *   https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#52-api-declaration</a>)
+ * Implementation of swagger spec (see <a href=
+ * "https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#52-api-declaration"
+ * > https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#52-api-
+ * declaration</a>)
  */
 public class ApiDeclaration {
-  private String apiVersion;
-  private String swaggerVersion;
-  private String basePath;
-  private String resourcePath;
-  private List<String> produces;
-  private List<Api> apis;
-  private JSONObject models;
-
-  public JSONObject getModels() {
-    return models;
-  }
-
-  public void setModels(JSONObject models) {
-    this.models = models;
-  }
-
-  public String getApiVersion() {
-    return apiVersion;
-  }
-
-  public void setApiVersion(String apiVersion) {
-    this.apiVersion = apiVersion;
-  }
-
-  public String getSwaggerVersion() {
-    return swaggerVersion;
-  }
-
-  public void setSwaggerVersion(String swaggerVersion) {
-    this.swaggerVersion = swaggerVersion;
-  }
-
-  public String getBasePath() {
-    return basePath;
-  }
-
-  public void setBasePath(String basePath) {
-    this.basePath = basePath;
-  }
-
-  public String getResourcePath() {
-    return resourcePath;
-  }
-
-  public void setResourcePath(String resourcePath) {
-    this.resourcePath = resourcePath;
-  }
-
-  public List<String> getProduces() {
-    return produces;
-  }
-
-  public void setProduces(List<String> produces) {
-    this.produces = produces;
-  }
-
-  public List<Api> getApis() {
-    return apis;
-  }
-
-  public void setApis(List<Api> apis) {
-    this.apis = apis;
-  }
-
-  public boolean hasApi(){
-    return (apis != null && !apis.isEmpty());
-  }
-
-  public boolean hasModel(){
-    return (models != null && models.length() > 0);
-  }
+    private String apiVersion;
+    private String swaggerVersion;
+    private String basePath;
+    private String resourcePath;
+    private List<String> produces;
+    private List<Api> apis;
+    private JSONObject models;
+
+    public JSONObject getModels() {
+        return models;
+    }
+
+    public void setModels(JSONObject models) {
+        this.models = models;
+    }
+
+    public String getApiVersion() {
+        return apiVersion;
+    }
+
+    public void setApiVersion(String apiVersion) {
+        this.apiVersion = apiVersion;
+    }
+
+    public String getSwaggerVersion() {
+        return swaggerVersion;
+    }
+
+    public void setSwaggerVersion(String swaggerVersion) {
+        this.swaggerVersion = swaggerVersion;
+    }
+
+    public String getBasePath() {
+        return basePath;
+    }
+
+    public void setBasePath(String basePath) {
+        this.basePath = basePath;
+    }
+
+    public String getResourcePath() {
+        return resourcePath;
+    }
+
+    public void setResourcePath(String resourcePath) {
+        this.resourcePath = resourcePath;
+    }
+
+    public List<String> getProduces() {
+        return produces;
+    }
+
+    public void setProduces(List<String> produces) {
+        this.produces = produces;
+    }
+
+    public List<Api> getApis() {
+        return apis;
+    }
+
+    public void setApis(List<Api> apis) {
+        this.apis = apis;
+    }
+
+    public boolean hasApi() {
+        return (apis != null && !apis.isEmpty());
+    }
+
+    public boolean hasModel() {
+        return (models != null && models.length() > 0);
+    }
 }
index d1150fd0bd426b6d0ba51a3d2c2417ce18d1ffc6..ba0c7966ecb856d4b21d8d1acd3e93785307d0b2 100644 (file)
@@ -10,81 +10,82 @@ package org.opendaylight.controller.sal.rest.doc.swagger;
 import java.util.List;
 
 /**
- * Implementation of swagger spec
- * (see <a href="https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#523-operation-object">
- *   https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#523-operation-object</a>)
+ * Implementation of swagger spec (see <a href=
+ * "https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#523-operation-object"
+ * > https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#523-
+ * operation-object</a>)
  */
 public class Operation {
-  private String method;
-  private String summary;
-  private String notes;
-  private String type;
-  private String nickname;
-  private List<String> consumes;
-  private List<Parameter> parameters;
-  private List<ResponseMessage> responseMessages;
-
-  public String getMethod() {
-    return method;
-  }
-
-  public void setMethod(String method) {
-    this.method = method;
-  }
-
-  public String getSummary() {
-    return summary;
-  }
-
-  public void setSummary(String summary) {
-    this.summary = summary;
-  }
-
-  public String getNotes() {
-    return notes;
-  }
-
-  public void setNotes(String notes) {
-    this.notes = notes;
-  }
-
-  public String getType() {
-    return type;
-  }
-
-  public void setType(String type) {
-    this.type = type;
-  }
-
-  public String getNickname() {
-    return nickname;
-  }
-
-  public void setNickname(String nickname) {
-    this.nickname = nickname;
-  }
-
-  public List<String> getConsumes() {
-    return consumes;
-  }
-
-  public void setConsumes(List<String> consumes) {
-    this.consumes = consumes;
-  }
-
-  public List<Parameter> getParameters() {
-    return parameters;
-  }
-
-  public void setParameters(List<Parameter> parameters) {
-    this.parameters = parameters;
-  }
-
-  public List<ResponseMessage> getResponseMessages() {
-    return responseMessages;
-  }
-
-  public void setResponseMessages(List<ResponseMessage> responseMessages) {
-    this.responseMessages = responseMessages;
-  }
+    private String method;
+    private String summary;
+    private String notes;
+    private String type;
+    private String nickname;
+    private List<String> consumes;
+    private List<Parameter> parameters;
+    private List<ResponseMessage> responseMessages;
+
+    public String getMethod() {
+        return method;
+    }
+
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+    public String getSummary() {
+        return summary;
+    }
+
+    public void setSummary(String summary) {
+        this.summary = summary;
+    }
+
+    public String getNotes() {
+        return notes;
+    }
+
+    public void setNotes(String notes) {
+        this.notes = notes;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getNickname() {
+        return nickname;
+    }
+
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    public List<String> getConsumes() {
+        return consumes;
+    }
+
+    public void setConsumes(List<String> consumes) {
+        this.consumes = consumes;
+    }
+
+    public List<Parameter> getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(List<Parameter> parameters) {
+        this.parameters = parameters;
+    }
+
+    public List<ResponseMessage> getResponseMessages() {
+        return responseMessages;
+    }
+
+    public void setResponseMessages(List<ResponseMessage> responseMessages) {
+        this.responseMessages = responseMessages;
+    }
 }
index dd56b9e854cb20e7d269e6006e14f326a7c0d010..41cec4db54c3a8553a628046a4e74825b2356da3 100644 (file)
@@ -8,54 +8,55 @@
 package org.opendaylight.controller.sal.rest.doc.swagger;
 
 /**
- * Implementation of swagger spec
- * (see <a href="https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#524-parameter-object">
- *   https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#524-parameter-object</a>)
+ * Implementation of swagger spec (see <a href=
+ * "https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#524-parameter-object"
+ * > https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#524-
+ * parameter-object</a>)
  */
 public class Parameter {
-  private String name;
-  private String description;
-  private boolean required;
-  private String type;
-  private String paramType;
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-
-  public String getDescription() {
-    return description;
-  }
-
-  public void setDescription(String description) {
-    this.description = description;
-  }
-
-  public boolean isRequired() {
-    return required;
-  }
-
-  public void setRequired(boolean required) {
-    this.required = required;
-  }
-
-  public String getType() {
-    return type;
-  }
-
-  public void setType(String type) {
-    this.type = type;
-  }
-
-  public String getParamType() {
-    return paramType;
-  }
-
-  public void setParamType(String paramType) {
-    this.paramType = paramType;
-  }
+    private String name;
+    private String description;
+    private boolean required;
+    private String type;
+    private String paramType;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public boolean isRequired() {
+        return required;
+    }
+
+    public void setRequired(boolean required) {
+        this.required = required;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getParamType() {
+        return paramType;
+    }
+
+    public void setParamType(String paramType) {
+        this.paramType = paramType;
+    }
 }
index c5c39799a89be9f80d2da3897a517bff816d3c49..cb5b200c60e97d4c8622749405d8ee1cc202d00e 100644 (file)
@@ -8,27 +8,28 @@
 package org.opendaylight.controller.sal.rest.doc.swagger;
 
 /**
- * Implementation of swagger spec
- * (see <a href="https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#512-resource-object">
- *   https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#512-resource-object</a>)
+ * Implementation of swagger spec (see <a href=
+ * "https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#512-resource-object"
+ * > https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#512-
+ * resource-object</a>)
  */
 public class Resource {
-  private String path;
-  private String description;
+    private String path;
+    private String description;
 
-  public String getPath() {
-    return path;
-  }
+    public String getPath() {
+        return path;
+    }
 
-  public void setPath(String path) {
-    this.path = path;
-  }
+    public void setPath(String path) {
+        this.path = path;
+    }
 
-  public String getDescription() {
-    return description;
-  }
+    public String getDescription() {
+        return description;
+    }
 
-  public void setDescription(String description) {
-    this.description = description;
-  }
+    public void setDescription(String description) {
+        this.description = description;
+    }
 }
index 9b1a106d0e9e4cc5f046d7353dd1c321b6149124..48362dc4edeba850898669100c5114764bc511f8 100644 (file)
@@ -10,36 +10,37 @@ package org.opendaylight.controller.sal.rest.doc.swagger;
 import java.util.List;
 
 /**
- * Implementation of swagger spec
- * (see <a href="https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#51-resource-listing">
- *   https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#51-resource-listing</a>)
+ * Implementation of swagger spec (see <a href=
+ * "https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#51-resource-listing"
+ * > https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#51-
+ * resource-listing</a>)
  */
 public class ResourceList {
-  private String apiVersion;
-  private String swaggerVersion;
-  private List<Resource> apis;
+    private String apiVersion;
+    private String swaggerVersion;
+    private List<Resource> apis;
 
-  public String getApiVersion() {
-    return apiVersion;
-  }
+    public String getApiVersion() {
+        return apiVersion;
+    }
 
-  public void setApiVersion(String apiVersion) {
-    this.apiVersion = apiVersion;
-  }
+    public void setApiVersion(String apiVersion) {
+        this.apiVersion = apiVersion;
+    }
 
-  public String getSwaggerVersion() {
-    return swaggerVersion;
-  }
+    public String getSwaggerVersion() {
+        return swaggerVersion;
+    }
 
-  public void setSwaggerVersion(String swaggerVersion) {
-    this.swaggerVersion = swaggerVersion;
-  }
+    public void setSwaggerVersion(String swaggerVersion) {
+        this.swaggerVersion = swaggerVersion;
+    }
 
-  public List<Resource> getApis() {
-    return apis;
-  }
+    public List<Resource> getApis() {
+        return apis;
+    }
 
-  public void setApis(List<Resource> apis) {
-    this.apis = apis;
-  }
+    public void setApis(List<Resource> apis) {
+        this.apis = apis;
+    }
 }
index 6c230992863be4274dde8896123d5aaf65083dc1..d82e1f4a81ddb15527db954052f106bb6b0f64eb 100644 (file)
@@ -8,27 +8,28 @@
 package org.opendaylight.controller.sal.rest.doc.swagger;
 
 /**
- * Implementation of swagger spec
- * (see <a href="https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#525-response-message-object">
- *   https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#525-response-message-object</a>)
+ * Implementation of swagger spec (see <a href=
+ * "https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#525-response-message-object"
+ * > https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#525-
+ * response-message-object</a>)
  */
 public class ResponseMessage {
-  private int code;
-  private String message;
+    private int code;
+    private String message;
 
-  public int getCode() {
-    return code;
-  }
+    public int getCode() {
+        return code;
+    }
 
-  public void setCode(int code) {
-    this.code = code;
-  }
+    public void setCode(int code) {
+        this.code = code;
+    }
 
-  public String getMessage() {
-    return message;
-  }
+    public String getMessage() {
+        return message;
+    }
 
-  public void setMessage(String message) {
-    this.message = message;
-  }
+    public void setMessage(String message) {
+        this.message = message;
+    }
 }
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/animated-overlay.gif b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/animated-overlay.gif
new file mode 100644 (file)
index 0000000..d441f75
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/animated-overlay.gif differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png
new file mode 100644 (file)
index 0000000..a28d678
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png
new file mode 100644 (file)
index 0000000..ab561d2
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png
new file mode 100644 (file)
index 0000000..be5c4c6
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png
new file mode 100644 (file)
index 0000000..c955a2c
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png
new file mode 100644 (file)
index 0000000..de7c46d
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644 (file)
index 0000000..6cc858e
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png
new file mode 100644 (file)
index 0000000..653f494
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
new file mode 100644 (file)
index 0000000..663b112
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
new file mode 100644 (file)
index 0000000..ee995d9
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_222222_256x240.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_222222_256x240.png
new file mode 100644 (file)
index 0000000..c1cb117
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_222222_256x240.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_228ef1_256x240.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_228ef1_256x240.png
new file mode 100644 (file)
index 0000000..3a0140c
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_228ef1_256x240.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ef8c08_256x240.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ef8c08_256x240.png
new file mode 100644 (file)
index 0000000..036ee07
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ef8c08_256x240.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ffd27a_256x240.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ffd27a_256x240.png
new file mode 100644 (file)
index 0000000..8b6c058
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ffd27a_256x240.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ffffff_256x240.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ffffff_256x240.png
new file mode 100644 (file)
index 0000000..4f624bb
Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/images/ui-icons_ffffff_256x240.png differ
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/jquery-ui-1.10.4.custom.css b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/jquery-ui-1.10.4.custom.css
new file mode 100644 (file)
index 0000000..a9aa9c4
--- /dev/null
@@ -0,0 +1,1178 @@
+/*! jQuery UI - v1.10.4 - 2014-06-03
+* http://jqueryui.com
+* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden {
+       display: none;
+}
+.ui-helper-hidden-accessible {
+       border: 0;
+       clip: rect(0 0 0 0);
+       height: 1px;
+       margin: -1px;
+       overflow: hidden;
+       padding: 0;
+       position: absolute;
+       width: 1px;
+}
+.ui-helper-reset {
+       margin: 0;
+       padding: 0;
+       border: 0;
+       outline: 0;
+       line-height: 1.3;
+       text-decoration: none;
+       font-size: 100%;
+       list-style: none;
+}
+.ui-helper-clearfix:before,
+.ui-helper-clearfix:after {
+       content: "";
+       display: table;
+       border-collapse: collapse;
+}
+.ui-helper-clearfix:after {
+       clear: both;
+}
+.ui-helper-clearfix {
+       min-height: 0; /* support: IE7 */
+}
+.ui-helper-zfix {
+       width: 100%;
+       height: 100%;
+       top: 0;
+       left: 0;
+       position: absolute;
+       opacity: 0;
+       filter:Alpha(Opacity=0);
+}
+
+.ui-front {
+       z-index: 100;
+}
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled {
+       cursor: default !important;
+}
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+       display: block;
+       text-indent: -99999px;
+       overflow: hidden;
+       background-repeat: no-repeat;
+}
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay {
+       position: fixed;
+       top: 0;
+       left: 0;
+       width: 100%;
+       height: 100%;
+}
+.ui-resizable {
+       position: relative;
+}
+.ui-resizable-handle {
+       position: absolute;
+       font-size: 0.1px;
+       display: block;
+}
+.ui-resizable-disabled .ui-resizable-handle,
+.ui-resizable-autohide .ui-resizable-handle {
+       display: none;
+}
+.ui-resizable-n {
+       cursor: n-resize;
+       height: 7px;
+       width: 100%;
+       top: -5px;
+       left: 0;
+}
+.ui-resizable-s {
+       cursor: s-resize;
+       height: 7px;
+       width: 100%;
+       bottom: -5px;
+       left: 0;
+}
+.ui-resizable-e {
+       cursor: e-resize;
+       width: 7px;
+       right: -5px;
+       top: 0;
+       height: 100%;
+}
+.ui-resizable-w {
+       cursor: w-resize;
+       width: 7px;
+       left: -5px;
+       top: 0;
+       height: 100%;
+}
+.ui-resizable-se {
+       cursor: se-resize;
+       width: 12px;
+       height: 12px;
+       right: 1px;
+       bottom: 1px;
+}
+.ui-resizable-sw {
+       cursor: sw-resize;
+       width: 9px;
+       height: 9px;
+       left: -5px;
+       bottom: -5px;
+}
+.ui-resizable-nw {
+       cursor: nw-resize;
+       width: 9px;
+       height: 9px;
+       left: -5px;
+       top: -5px;
+}
+.ui-resizable-ne {
+       cursor: ne-resize;
+       width: 9px;
+       height: 9px;
+       right: -5px;
+       top: -5px;
+}
+.ui-selectable-helper {
+       position: absolute;
+       z-index: 100;
+       border: 1px dotted black;
+}
+.ui-accordion .ui-accordion-header {
+       display: block;
+       cursor: pointer;
+       position: relative;
+       margin-top: 2px;
+       padding: .5em .5em .5em .7em;
+       min-height: 0; /* support: IE7 */
+}
+.ui-accordion .ui-accordion-icons {
+       padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-noicons {
+       padding-left: .7em;
+}
+.ui-accordion .ui-accordion-icons .ui-accordion-icons {
+       padding-left: 2.2em;
+}
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
+       position: absolute;
+       left: .5em;
+       top: 50%;
+       margin-top: -8px;
+}
+.ui-accordion .ui-accordion-content {
+       padding: 1em 2.2em;
+       border-top: 0;
+       overflow: auto;
+}
+.ui-autocomplete {
+       position: absolute;
+       top: 0;
+       left: 0;
+       cursor: default;
+}
+.ui-button {
+       display: inline-block;
+       position: relative;
+       padding: 0;
+       line-height: normal;
+       margin-right: .1em;
+       cursor: pointer;
+       vertical-align: middle;
+       text-align: center;
+       overflow: visible; /* removes extra width in IE */
+}
+.ui-button,
+.ui-button:link,
+.ui-button:visited,
+.ui-button:hover,
+.ui-button:active {
+       text-decoration: none;
+}
+/* to make room for the icon, a width needs to be set here */
+.ui-button-icon-only {
+       width: 2.2em;
+}
+/* button elements seem to need a little more width */
+button.ui-button-icon-only {
+       width: 2.4em;
+}
+.ui-button-icons-only {
+       width: 3.4em;
+}
+button.ui-button-icons-only {
+       width: 3.7em;
+}
+
+/* button text element */
+.ui-button .ui-button-text {
+       display: block;
+       line-height: normal;
+}
+.ui-button-text-only .ui-button-text {
+       padding: .4em 1em;
+}
+.ui-button-icon-only .ui-button-text,
+.ui-button-icons-only .ui-button-text {
+       padding: .4em;
+       text-indent: -9999999px;
+}
+.ui-button-text-icon-primary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+       padding: .4em 1em .4em 2.1em;
+}
+.ui-button-text-icon-secondary .ui-button-text,
+.ui-button-text-icons .ui-button-text {
+       padding: .4em 2.1em .4em 1em;
+}
+.ui-button-text-icons .ui-button-text {
+       padding-left: 2.1em;
+       padding-right: 2.1em;
+}
+/* no icon support for input elements, provide padding by default */
+input.ui-button {
+       padding: .4em 1em;
+}
+
+/* button icon element(s) */
+.ui-button-icon-only .ui-icon,
+.ui-button-text-icon-primary .ui-icon,
+.ui-button-text-icon-secondary .ui-icon,
+.ui-button-text-icons .ui-icon,
+.ui-button-icons-only .ui-icon {
+       position: absolute;
+       top: 50%;
+       margin-top: -8px;
+}
+.ui-button-icon-only .ui-icon {
+       left: 50%;
+       margin-left: -8px;
+}
+.ui-button-text-icon-primary .ui-button-icon-primary,
+.ui-button-text-icons .ui-button-icon-primary,
+.ui-button-icons-only .ui-button-icon-primary {
+       left: .5em;
+}
+.ui-button-text-icon-secondary .ui-button-icon-secondary,
+.ui-button-text-icons .ui-button-icon-secondary,
+.ui-button-icons-only .ui-button-icon-secondary {
+       right: .5em;
+}
+
+/* button sets */
+.ui-buttonset {
+       margin-right: 7px;
+}
+.ui-buttonset .ui-button {
+       margin-left: 0;
+       margin-right: -.3em;
+}
+
+/* workarounds */
+/* reset extra padding in Firefox, see h5bp.com/l */
+input.ui-button::-moz-focus-inner,
+button.ui-button::-moz-focus-inner {
+       border: 0;
+       padding: 0;
+}
+.ui-datepicker {
+       width: 17em;
+       padding: .2em .2em 0;
+       display: none;
+}
+.ui-datepicker .ui-datepicker-header {
+       position: relative;
+       padding: .2em 0;
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+       position: absolute;
+       top: 2px;
+       width: 1.8em;
+       height: 1.8em;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+       top: 1px;
+}
+.ui-datepicker .ui-datepicker-prev {
+       left: 2px;
+}
+.ui-datepicker .ui-datepicker-next {
+       right: 2px;
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+       left: 1px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+       right: 1px;
+}
+.ui-datepicker .ui-datepicker-prev span,
+.ui-datepicker .ui-datepicker-next span {
+       display: block;
+       position: absolute;
+       left: 50%;
+       margin-left: -8px;
+       top: 50%;
+       margin-top: -8px;
+}
+.ui-datepicker .ui-datepicker-title {
+       margin: 0 2.3em;
+       line-height: 1.8em;
+       text-align: center;
+}
+.ui-datepicker .ui-datepicker-title select {
+       font-size: 1em;
+       margin: 1px 0;
+}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year {
+       width: 49%;
+}
+.ui-datepicker table {
+       width: 100%;
+       font-size: .9em;
+       border-collapse: collapse;
+       margin: 0 0 .4em;
+}
+.ui-datepicker th {
+       padding: .7em .3em;
+       text-align: center;
+       font-weight: bold;
+       border: 0;
+}
+.ui-datepicker td {
+       border: 0;
+       padding: 1px;
+}
+.ui-datepicker td span,
+.ui-datepicker td a {
+       display: block;
+       padding: .2em;
+       text-align: right;
+       text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-buttonpane {
+       background-image: none;
+       margin: .7em 0 0 0;
+       padding: 0 .2em;
+       border-left: 0;
+       border-right: 0;
+       border-bottom: 0;
+}
+.ui-datepicker .ui-datepicker-buttonpane button {
+       float: right;
+       margin: .5em .2em .4em;
+       cursor: pointer;
+       padding: .2em .6em .3em .6em;
+       width: auto;
+       overflow: visible;
+}
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
+       float: left;
+}
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi {
+       width: auto;
+}
+.ui-datepicker-multi .ui-datepicker-group {
+       float: left;
+}
+.ui-datepicker-multi .ui-datepicker-group table {
+       width: 95%;
+       margin: 0 auto .4em;
+}
+.ui-datepicker-multi-2 .ui-datepicker-group {
+       width: 50%;
+}
+.ui-datepicker-multi-3 .ui-datepicker-group {
+       width: 33.3%;
+}
+.ui-datepicker-multi-4 .ui-datepicker-group {
+       width: 25%;
+}
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
+       border-left-width: 0;
+}
+.ui-datepicker-multi .ui-datepicker-buttonpane {
+       clear: left;
+}
+.ui-datepicker-row-break {
+       clear: both;
+       width: 100%;
+       font-size: 0;
+}
+
+/* RTL support */
+.ui-datepicker-rtl {
+       direction: rtl;
+}
+.ui-datepicker-rtl .ui-datepicker-prev {
+       right: 2px;
+       left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next {
+       left: 2px;
+       right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-prev:hover {
+       right: 1px;
+       left: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-next:hover {
+       left: 1px;
+       right: auto;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane {
+       clear: right;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {
+       float: left;
+}
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
+.ui-datepicker-rtl .ui-datepicker-group {
+       float: right;
+}
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
+       border-right-width: 0;
+       border-left-width: 1px;
+}
+.ui-dialog {
+       overflow: hidden;
+       position: absolute;
+       top: 0;
+       left: 0;
+       padding: .2em;
+       outline: 0;
+}
+.ui-dialog .ui-dialog-titlebar {
+       padding: .4em 1em;
+       position: relative;
+}
+.ui-dialog .ui-dialog-title {
+       float: left;
+       margin: .1em 0;
+       white-space: nowrap;
+       width: 90%;
+       overflow: hidden;
+       text-overflow: ellipsis;
+}
+.ui-dialog .ui-dialog-titlebar-close {
+       position: absolute;
+       right: .3em;
+       top: 50%;
+       width: 20px;
+       margin: -10px 0 0 0;
+       padding: 1px;
+       height: 20px;
+}
+.ui-dialog .ui-dialog-content {
+       position: relative;
+       border: 0;
+       padding: .5em 1em;
+       background: none;
+       overflow: auto;
+}
+.ui-dialog .ui-dialog-buttonpane {
+       text-align: left;
+       border-width: 1px 0 0 0;
+       background-image: none;
+       margin-top: .5em;
+       padding: .3em 1em .5em .4em;
+}
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+       float: right;
+}
+.ui-dialog .ui-dialog-buttonpane button {
+       margin: .5em .4em .5em 0;
+       cursor: pointer;
+}
+.ui-dialog .ui-resizable-se {
+       width: 12px;
+       height: 12px;
+       right: -5px;
+       bottom: -5px;
+       background-position: 16px 16px;
+}
+.ui-draggable .ui-dialog-titlebar {
+       cursor: move;
+}
+.ui-menu {
+       list-style: none;
+       padding: 2px;
+       margin: 0;
+       display: block;
+       outline: none;
+}
+.ui-menu .ui-menu {
+       margin-top: -3px;
+       position: absolute;
+}
+.ui-menu .ui-menu-item {
+       margin: 0;
+       padding: 0;
+       width: 100%;
+       /* support: IE10, see #8844 */
+       list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
+}
+.ui-menu .ui-menu-divider {
+       margin: 5px -2px 5px -2px;
+       height: 0;
+       font-size: 0;
+       line-height: 0;
+       border-width: 1px 0 0 0;
+}
+.ui-menu .ui-menu-item a {
+       text-decoration: none;
+       display: block;
+       padding: 2px .4em;
+       line-height: 1.5;
+       min-height: 0; /* support: IE7 */
+       font-weight: normal;
+}
+.ui-menu .ui-menu-item a.ui-state-focus,
+.ui-menu .ui-menu-item a.ui-state-active {
+       font-weight: normal;
+       margin: -1px;
+}
+
+.ui-menu .ui-state-disabled {
+       font-weight: normal;
+       margin: .4em 0 .2em;
+       line-height: 1.5;
+}
+.ui-menu .ui-state-disabled a {
+       cursor: default;
+}
+
+/* icon support */
+.ui-menu-icons {
+       position: relative;
+}
+.ui-menu-icons .ui-menu-item a {
+       position: relative;
+       padding-left: 2em;
+}
+
+/* left-aligned */
+.ui-menu .ui-icon {
+       position: absolute;
+       top: .2em;
+       left: .2em;
+}
+
+/* right-aligned */
+.ui-menu .ui-menu-icon {
+       position: static;
+       float: right;
+}
+.ui-progressbar {
+       height: 2em;
+       text-align: left;
+       overflow: hidden;
+}
+.ui-progressbar .ui-progressbar-value {
+       margin: -1px;
+       height: 100%;
+}
+.ui-progressbar .ui-progressbar-overlay {
+       background: url("images/animated-overlay.gif");
+       height: 100%;
+       filter: alpha(opacity=25);
+       opacity: 0.25;
+}
+.ui-progressbar-indeterminate .ui-progressbar-value {
+       background-image: none;
+}
+.ui-slider {
+       position: relative;
+       text-align: left;
+}
+.ui-slider .ui-slider-handle {
+       position: absolute;
+       z-index: 2;
+       width: 1.2em;
+       height: 1.2em;
+       cursor: default;
+}
+.ui-slider .ui-slider-range {
+       position: absolute;
+       z-index: 1;
+       font-size: .7em;
+       display: block;
+       border: 0;
+       background-position: 0 0;
+}
+
+/* For IE8 - See #6727 */
+.ui-slider.ui-state-disabled .ui-slider-handle,
+.ui-slider.ui-state-disabled .ui-slider-range {
+       filter: inherit;
+}
+
+.ui-slider-horizontal {
+       height: .8em;
+}
+.ui-slider-horizontal .ui-slider-handle {
+       top: -.3em;
+       margin-left: -.6em;
+}
+.ui-slider-horizontal .ui-slider-range {
+       top: 0;
+       height: 100%;
+}
+.ui-slider-horizontal .ui-slider-range-min {
+       left: 0;
+}
+.ui-slider-horizontal .ui-slider-range-max {
+       right: 0;
+}
+
+.ui-slider-vertical {
+       width: .8em;
+       height: 100px;
+}
+.ui-slider-vertical .ui-slider-handle {
+       left: -.3em;
+       margin-left: 0;
+       margin-bottom: -.6em;
+}
+.ui-slider-vertical .ui-slider-range {
+       left: 0;
+       width: 100%;
+}
+.ui-slider-vertical .ui-slider-range-min {
+       bottom: 0;
+}
+.ui-slider-vertical .ui-slider-range-max {
+       top: 0;
+}
+.ui-spinner {
+       position: relative;
+       display: inline-block;
+       overflow: hidden;
+       padding: 0;
+       vertical-align: middle;
+}
+.ui-spinner-input {
+       border: none;
+       background: none;
+       color: inherit;
+       padding: 0;
+       margin: .2em 0;
+       vertical-align: middle;
+       margin-left: .4em;
+       margin-right: 22px;
+}
+.ui-spinner-button {
+       width: 16px;
+       height: 50%;
+       font-size: .5em;
+       padding: 0;
+       margin: 0;
+       text-align: center;
+       position: absolute;
+       cursor: default;
+       display: block;
+       overflow: hidden;
+       right: 0;
+}
+/* more specificity required here to override default borders */
+.ui-spinner a.ui-spinner-button {
+       border-top: none;
+       border-bottom: none;
+       border-right: none;
+}
+/* vertically center icon */
+.ui-spinner .ui-icon {
+       position: absolute;
+       margin-top: -8px;
+       top: 50%;
+       left: 0;
+}
+.ui-spinner-up {
+       top: 0;
+}
+.ui-spinner-down {
+       bottom: 0;
+}
+
+/* TR overrides */
+.ui-spinner .ui-icon-triangle-1-s {
+       /* need to fix icons sprite */
+       background-position: -65px -16px;
+}
+.ui-tabs {
+       position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+       padding: .2em;
+}
+.ui-tabs .ui-tabs-nav {
+       margin: 0;
+       padding: .2em .2em 0;
+}
+.ui-tabs .ui-tabs-nav li {
+       list-style: none;
+       float: left;
+       position: relative;
+       top: 0;
+       margin: 1px .2em 0 0;
+       border-bottom-width: 0;
+       padding: 0;
+       white-space: nowrap;
+}
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+       float: left;
+       padding: .5em 1em;
+       text-decoration: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+       margin-bottom: -1px;
+       padding-bottom: 1px;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
+       cursor: text;
+}
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
+       cursor: pointer;
+}
+.ui-tabs .ui-tabs-panel {
+       display: block;
+       border-width: 0;
+       padding: 1em 1.4em;
+       background: none;
+}
+.ui-tooltip {
+       padding: 8px;
+       position: absolute;
+       z-index: 9999;
+       max-width: 300px;
+       -webkit-box-shadow: 0 0 5px #aaa;
+       box-shadow: 0 0 5px #aaa;
+}
+body .ui-tooltip {
+       border-width: 2px;
+}
+
+/* Component containers
+----------------------------------*/
+.ui-widget {
+       font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
+       font-size: 1.1em;
+}
+.ui-widget .ui-widget {
+       font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+       font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
+       font-size: 1em;
+}
+.ui-widget-content {
+       border: 1px solid #dddddd;
+       background: #eeeeee url("images/ui-bg_highlight-soft_100_eeeeee_1x100.png") 50% top repeat-x;
+       color: #333333;
+}
+.ui-widget-content a {
+       color: #333333;
+}
+.ui-widget-header {
+       border: 1px solid #e78f08;
+       background: #f6a828 url("images/ui-bg_gloss-wave_35_f6a828_500x100.png") 50% 50% repeat-x;
+       color: #ffffff;
+       font-weight: bold;
+}
+.ui-widget-header a {
+       color: #ffffff;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default {
+       border: 1px solid #cccccc;
+       background: #f6f6f6 url("images/ui-bg_glass_100_f6f6f6_1x400.png") 50% 50% repeat-x;
+       font-weight: bold;
+       color: #1c94c4;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited {
+       color: #1c94c4;
+       text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus {
+       border: 1px solid #fbcb09;
+       background: #fdf5ce url("images/ui-bg_glass_100_fdf5ce_1x400.png") 50% 50% repeat-x;
+       font-weight: bold;
+       color: #c77405;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited,
+.ui-state-focus a,
+.ui-state-focus a:hover,
+.ui-state-focus a:link,
+.ui-state-focus a:visited {
+       color: #c77405;
+       text-decoration: none;
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active {
+       border: 1px solid #fbd850;
+       background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
+       font-weight: bold;
+       color: #eb8f00;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+       color: #eb8f00;
+       text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+       border: 1px solid #fed22f;
+       background: #ffe45c url("images/ui-bg_highlight-soft_75_ffe45c_1x100.png") 50% top repeat-x;
+       color: #363636;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+       color: #363636;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+       border: 1px solid #cd0a0a;
+       background: #b81900 url("images/ui-bg_diagonals-thick_18_b81900_40x40.png") 50% 50% repeat;
+       color: #ffffff;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+       color: #ffffff;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+       color: #ffffff;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+       font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+       opacity: .7;
+       filter:Alpha(Opacity=70);
+       font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+       opacity: .35;
+       filter:Alpha(Opacity=35);
+       background-image: none;
+}
+.ui-state-disabled .ui-icon {
+       filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+       width: 16px;
+       height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+       background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-widget-header .ui-icon {
+       background-image: url("images/ui-icons_ffffff_256x240.png");
+}
+.ui-state-default .ui-icon {
+       background-image: url("images/ui-icons_ef8c08_256x240.png");
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon {
+       background-image: url("images/ui-icons_ef8c08_256x240.png");
+}
+.ui-state-active .ui-icon {
+       background-image: url("images/ui-icons_ef8c08_256x240.png");
+}
+.ui-state-highlight .ui-icon {
+       background-image: url("images/ui-icons_228ef1_256x240.png");
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+       background-image: url("images/ui-icons_ffd27a_256x240.png");
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+       border-top-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+       border-top-right-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+       border-bottom-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+       border-bottom-right-radius: 4px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+       background: #666666 url("images/ui-bg_diagonals-thick_20_666666_40x40.png") 50% 50% repeat;
+       opacity: .5;
+       filter: Alpha(Opacity=50);
+}
+.ui-widget-shadow {
+       margin: -5px 0 0 -5px;
+       padding: 5px;
+       background: #000000 url("images/ui-bg_flat_10_000000_40x100.png") 50% 50% repeat-x;
+       opacity: .2;
+       filter: Alpha(Opacity=20);
+       border-radius: 5px;
+}
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/jquery-ui-1.10.4.custom.min.css b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/ui-lightness/jquery-ui-1.10.4.custom.min.css
new file mode 100644 (file)
index 0000000..b1f2f3c
--- /dev/null
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.10.4 - 2014-06-03
+* http://jqueryui.com
+* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:none}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:normal}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:normal;margin:-1px}.ui-menu .ui-state-disabled{font-weight:normal;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("images/animated-overlay.gif");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url("images/ui-bg_highlight-soft_100_eeeeee_1x100.png") 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url("images/ui-bg_gloss-wave_35_f6a828_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url("images/ui-bg_glass_100_f6f6f6_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url("images/ui-bg_glass_100_fdf5ce_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url("images/ui-bg_highlight-soft_75_ffe45c_1x100.png") 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url("images/ui-bg_diagonals-thick_18_b81900_40x40.png") 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_228ef1_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_ffd27a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url("images/ui-bg_diagonals-thick_20_666666_40x40.png") 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url("images/ui-bg_flat_10_000000_40x100.png") 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px}
\ No newline at end of file
index 5496a65579ae903d4008f9d268fac422ef9d3679..46c02e2aeb311b5462d09b26b4ad0dd2b326720c 100644 (file)
Binary files a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/logo_small.png and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/logo_small.png differ
index b8f67750c369e819bae4352b17713b10a7d3bdbf..2816f79e2413a90afc4125346a1a64804658a548 100644 (file)
 <!DOCTYPE html>\r
 <html>\r
 <head>\r
-  <title>Swagger UI</title>\r
-  <link href='//fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>\r
-  <link href='css/highlight.default.css' media='screen' rel='stylesheet' type='text/css'/>\r
-  <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>\r
-  <script type="text/javascript" src="lib/shred.bundle.js" /></script>  \r
-  <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>\r
-  <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>\r
-  <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>\r
-  <script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>\r
-  <script src='lib/handlebars-1.0.0.js' type='text/javascript'></script>\r
-  <script src='lib/underscore-min.js' type='text/javascript'></script>\r
-  <script src='lib/backbone-min.js' type='text/javascript'></script>\r
-  <script src='lib/swagger.js' type='text/javascript'></script>\r
-  <script src='swagger-ui.js' type='text/javascript'></script>\r
-  <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>\r
-  <script type="text/javascript">\r
-    $(function () {\r
-      window.swaggerUi = new SwaggerUi({\r
-      url: "http://localhost:8080/apidoc/apis",\r
-      dom_id: "swagger-ui-container",\r
-      supportedSubmitMethods: ['get', 'post', 'put', 'delete'],\r
-      onComplete: function(swaggerApi, swaggerUi){\r
-        if(console) {\r
-          console.log("Loaded SwaggerUI")\r
-        }\r
-        $('pre code').each(function(i, e) {hljs.highlightBlock(e)});\r
-      },\r
-      onFailure: function(data) {\r
-        if(console) {\r
-          console.log("Unable to Load SwaggerUI");\r
-          console.log(data);\r
-        }\r
-      },\r
-      docExpansion: "none"\r
-    });\r
+<title>RestConf Documentation</title>\r
+<link href='//fonts.googleapis.com/css?family=Droid+Sans:400,700'\r
+       rel='stylesheet' type='text/css' />\r
+<link href='css/highlight.default.css' media='screen' rel='stylesheet'\r
+       type='text/css' />\r
+<link href='css/screen.css' media='screen' rel='stylesheet'\r
+       type='text/css' />\r
+<link rel="stylesheet" type="text/css" href="/css/opendaylight.css">\r
+<link rel="stylesheet" type="text/css"\r
+       href="css/ui-lightness/jquery-ui-1.10.4.custom.min.css">\r
+<script type="text/javascript" src="lib/shred.bundle.js"></script>\r
+<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>\r
+<script src='lib/jquery-ui-1.11.0.min.js' type="text/javascript"></script>\r
+<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>\r
+<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>\r
+<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>\r
+<script src='lib/handlebars-1.0.0.js' type='text/javascript'></script>\r
+<script src='lib/underscore-min.js' type='text/javascript'></script>\r
+<script src='lib/backbone-min.js' type='text/javascript'></script>\r
+<script src='lib/swagger.js' type='text/javascript'></script>\r
+<script src='swagger-ui.js' type='text/javascript'></script>\r
+<script src='lib/odl/list_mounts.js' type='text/javascript'></script>\r
+<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>\r
+<script src='lib/odl/rest-tree.js' type='text/javascript'></script>\r
+<script src='lib/odl/swagger.js' type='text/javascript'></script>\r
 \r
-    $('#input_apiKey').change(function() {\r
-      var key = $('#input_apiKey')[0].value;\r
-      console.log("key: " + key);\r
-      if(key && key.trim() != "") {\r
-        console.log("added key " + key);\r
-        window.authorizations.add("key", new ApiKeyAuthorization("api_key", key, "query"));\r
-      }\r
-    })\r
-    window.swaggerUi.load();\r
-  });\r
+<script type="text/javascript">\r
+       \r
+       //reloads the swagger UI documentation for the specified mount.\r
+       var loadMount = function(mountIndex, mountPath) {\r
+               $("#message").empty();\r
+               $("#message").append( "<p>Loading...</p>" );\r
+               loadSwagger("http://localhost:8080/apidoc/apis/mounts/" + mountIndex,\r
+                               "swagger-ui-container");\r
+               $("#message").empty();\r
+               $("#message").append( "<h2><b>Showing mount points for " + mountPath + "</b></h2>");\r
+       }\r
 \r
-  </script>\r
+       //clears the swagger UI and adds text prompting use to select a mount point.\r
+    var selectAMount = function(string) {\r
+        $("#swagger-ui-container").empty();\r
+        $("#message").empty();\r
+        $("#message").append("<p>Select a mount point.</p>");\r
+    }\r
+    \r
+       //loads the root swagger documenation (which comes from RestConf)\r
+       var loadRootSwagger = function() {\r
+               $("#message").empty();\r
+               loadSwagger("http://localhost:8080/apidoc/apis", "swagger-ui-container");\r
+       }\r
+\r
+       //main method to initialize the mount list / swagger docs / tabs on page load\r
+       $(function() {\r
+               $("#tabs").tabs();\r
+\r
+               loadMountList($("#mountlist"));\r
+\r
+               loadRootSwagger();\r
+       });\r
+</script>\r
 </head>\r
 \r
 <body>\r
-<div id='header'>\r
-  <div class="swagger-ui-wrap">\r
-    <a id="logo" href="http://swagger.wordnik.com">swagger</a>\r
-\r
-    <form id='api_selector'>\r
-      <div class='input icon-btn'>\r
-        <img id="show-pet-store-icon" src="images/pet_store_api.png" title="Show Swagger Petstore Example Apis">\r
-      </div>\r
-      <div class='input icon-btn'>\r
-        <img id="show-wordnik-dev-icon" src="images/wordnik_api.png" title="Show Wordnik Developer Apis">\r
-      </div>\r
-      <div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div>\r
-      <div class='input'><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>\r
-      <div class='input'><a id="explore" href="#">Explore</a></div>\r
-    </form>\r
-  </div>\r
-</div>\r
+       <div>\r
+               <!-- style="background-color: #FCA000;" -->\r
+               <div class="swagger-ui-wrap ui-tabs">\r
+                       <table>\r
+                               <tr>\r
+                                       <td><img src="images/logo_small.png" /></td>\r
+                                       <td><h1 width="100%">OpenDaylight RestConf API\r
+                                                       Documentation</h1></td>\r
+                               </tr>\r
+                       </table>\r
+               </div>\r
+       </div>\r
 \r
-<div id="message-bar" class="swagger-ui-wrap">\r
-  &nbsp;\r
-</div>\r
+       <div class="navbar-inner">\r
+               <div class="brand"></div>\r
+       </div>\r
 \r
-<div id="swagger-ui-container" class="swagger-ui-wrap">\r
+    <!--  defines the div shells which represent the jquery tabs -->\r
+       <div id="tabs" class="swagger-ui-wrap">\r
+               <ul>\r
+                       <li><a href="#Controller" onclick="loadRootSwagger()">Controller\r
+                                       Resources</a></li>\r
+                       <li><a href="#Mounts" onclick="selectAMount()">Mounted\r
+                                       Resources</a></li>\r
+               </ul>\r
 \r
-</div>\r
+               <div id="Controller">\r
+                       <div>\r
+                               <h3>Below are the list of APIs supported by the Controller.</h3>\r
+                       </div>\r
+               </div>\r
+               <div id="Mounts">\r
+                       <div>\r
+                               <h3>Mount Points - Select an API below for details on available\r
+                                       queries.</h3>\r
+                       </div>\r
+                       <div id="mountlist"></div>\r
+               </div>\r
+       </div>\r
+       \r
+       <div class="swagger-ui-wrap"><hr/></div>\r
+       \r
+       <!-- messages -->\r
+       <div id="message" class="swagger-ui-wrap"></div>\r
+       \r
+       <!-- the swagger is always loaded in this div -->\r
+       <div id="swagger-ui-container" class="swagger-ui-wrap"></div>\r
 \r
+       <div id="message-bar" class="swagger-ui-wrap">&nbsp;</div>\r
 </body>\r
 \r
 </html>\r
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/jquery-ui-1.11.0.min.js b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/jquery-ui-1.11.0.min.js
new file mode 100644 (file)
index 0000000..0e0a79e
--- /dev/null
@@ -0,0 +1,13 @@
+/*! jQuery UI - v1.11.0-beta.2 - 2014-06-08
+* http://jqueryui.com
+* Includes: core.js, widget.js, mouse.js, position.js, draggable.js, droppable.js, resizable.js, selectable.js, sortable.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, menu.js, progressbar.js, selectmenu.js, slider.js, spinner.js, tabs.js, tooltip.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,i){var r,s,n,o=t.nodeName.toLowerCase();return"area"===o?(r=t.parentNode,s=r.name,t.href&&s&&"map"===r.nodeName.toLowerCase()?(n=e("img[usemap=#"+s+"]")[0],!!n&&a(n)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&a(t)}function a(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}function i(e){for(var t,a;e.length&&e[0]!==document;){if(t=e.css("position"),("absolute"===t||"relative"===t||"fixed"===t)&&(a=parseInt(e.css("zIndex"),10),!isNaN(a)&&0!==a))return a;e=e.parent()}return 0}function r(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.dpDiv=s(e("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function s(t){var a="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(a,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(a,"mouseover",function(){e.datepicker._isDisabledDatepicker(g.inline?t.parent()[0]:g.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))})}function n(t,a){e.extend(t,a);for(var i in a)null==a[i]&&(t[i]=a[i]);return t}function o(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.0-beta.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(){var t=this.css("position"),a="absolute"===t,i=this.parents().filter(function(){var t=e(this);return a&&"static"===t.css("position")?!1:/(auto|scroll)/.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==t&&i.length?i:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(a){return!!e.data(a,t)}}):function(t,a,i){return!!e.data(t,i[3])},focusable:function(a){return t(a,!isNaN(e.attr(a,"tabindex")))},tabbable:function(a){var i=e.attr(a,"tabindex"),r=isNaN(i);return(r||i>=0)&&t(a,!r)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(t,a){function i(t,a,i,s){return e.each(r,function(){a-=parseFloat(e.css(t,"padding"+this))||0,i&&(a-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(a-=parseFloat(e.css(t,"margin"+this))||0)}),a}var r="Width"===a?["Left","Right"]:["Top","Bottom"],s=a.toLowerCase(),n={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+a]=function(t){return void 0===t?n["inner"+a].call(this):this.each(function(){e(this).css(s,i(this,t)+"px")})},e.fn["outer"+a]=function(t,r){return"number"!=typeof t?n["outer"+a].call(this,t):this.each(function(){e(this).css(s,i(this,t,!0,r)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(a){return arguments.length?t.call(this,e.camelCase(a)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(a,i){return"number"==typeof a?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),i&&i.call(t)},a)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var a,i,r=e(this[0]);r.length&&r[0]!==document;){if(a=r.css("position"),("absolute"===a||"relative"===a||"fixed"===a)&&(i=parseInt(r.css("zIndex"),10),!isNaN(i)&&0!==i))return i;r=r.parent()}return 0}}),e.ui.plugin={add:function(t,a,i){var r,s=e.ui[t].prototype;for(r in i)s.plugins[r]=s.plugins[r]||[],s.plugins[r].push([a,i[r]])},call:function(e,t,a,i){var r,s=e.plugins[t];if(s&&(i||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(r=0;s.length>r;r++)e.options[s[r][0]]&&s[r][1].apply(e.element,a)}};var d=0,u=Array.prototype.slice;e.cleanData=function(t){return function(a){for(var i,r=0;null!=(i=a[r]);r++)try{e(i).triggerHandler("remove")}catch(s){}t(a)}}(e.cleanData),e.widget=function(t,a,i){var r,s,n,o,d={},u=t.split(".")[0];return t=t.split(".")[1],r=u+"-"+t,i||(i=a,a=e.Widget),e.expr[":"][r.toLowerCase()]=function(t){return!!e.data(t,r)},e[u]=e[u]||{},s=e[u][t],n=e[u][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new n(e,t)},e.extend(n,s,{version:i.version,_proto:e.extend({},i),_childConstructors:[]}),o=new a,o.options=e.widget.extend({},o.options),e.each(i,function(t,i){return e.isFunction(i)?(d[t]=function(){var e=function(){return a.prototype[t].apply(this,arguments)},r=function(e){return a.prototype[t].apply(this,e)};return function(){var t,a=this._super,s=this._superApply;return this._super=e,this._superApply=r,t=i.apply(this,arguments),this._super=a,this._superApply=s,t}}(),void 0):(d[t]=i,void 0)}),n.prototype=e.widget.extend(o,{widgetEventPrefix:s?o.widgetEventPrefix||t:t},d,{constructor:n,namespace:u,widgetName:t,widgetFullName:r}),s?(e.each(s._childConstructors,function(t,a){var i=a.prototype;e.widget(i.namespace+"."+i.widgetName,n,a._proto)}),delete s._childConstructors):a._childConstructors.push(n),e.widget.bridge(t,n),n},e.widget.extend=function(t){for(var a,i,r=u.call(arguments,1),s=0,n=r.length;n>s;s++)for(a in r[s])i=r[s][a],r[s].hasOwnProperty(a)&&void 0!==i&&(t[a]=e.isPlainObject(i)?e.isPlainObject(t[a])?e.widget.extend({},t[a],i):e.widget.extend({},i):i);return t},e.widget.bridge=function(t,a){var i=a.prototype.widgetFullName||t;e.fn[t]=function(r){var s="string"==typeof r,n=u.call(arguments,1),o=this;return r=!s&&n.length?e.widget.extend.apply(null,[r].concat(n)):r,s?this.each(function(){var a,s=e.data(this,i);return"instance"===r?(o=s,!1):s?e.isFunction(s[r])&&"_"!==r.charAt(0)?(a=s[r].apply(s,n),a!==s&&void 0!==a?(o=a&&a.jquery?o.pushStack(a.get()):a,!1):void 0):e.error("no such method '"+r+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,i);t?(t.option(r||{}),t._init&&t._init()):e.data(this,i,new a(r,this))}),o}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,a){a=e(a||this.defaultElement||this)[0],this.element=e(a),this.uuid=d++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),a!==this&&(e.data(a,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===a&&this.destroy()}}),this.document=e(a.style?a.ownerDocument:a.document||a),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,a){var i,r,s,n=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(n={},i=t.split("."),t=i.shift(),i.length){for(r=n[t]=e.widget.extend({},this.options[t]),s=0;i.length-1>s;s++)r[i[s]]=r[i[s]]||{},r=r[i[s]];if(t=i.pop(),1===arguments.length)return void 0===r[t]?null:r[t];r[t]=a}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];n[t]=a}return this._setOptions(n),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,a,i){var r,s=this;"boolean"!=typeof t&&(i=a,a=t,t=!1),i?(a=r=e(a),this.bindings=this.bindings.add(a)):(i=a,a=this.element,r=this.widget()),e.each(i,function(i,n){function o(){return t||s.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof n?s[n]:n).apply(s,arguments):void 0}"string"!=typeof n&&(o.guid=n.guid=n.guid||o.guid||e.guid++);var d=i.match(/^([\w:-]*)\s*(.*)$/),u=d[1]+s.eventNamespace,h=d[2];h?r.delegate(h,u,o):a.bind(u,o)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function a(){return("string"==typeof e?i[e]:e).apply(i,arguments)}var i=this;return setTimeout(a,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,a,i){var r,s,n=this.options[t];if(i=i||{},a=e.Event(a),a.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),a.target=this.element[0],s=a.originalEvent)for(r in s)r in a||(a[r]=s[r]);return this.element.trigger(a,i),!(e.isFunction(n)&&n.apply(this.element[0],[a].concat(i))===!1||a.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,a){e.Widget.prototype["_"+t]=function(i,r,s){"string"==typeof r&&(r={effect:r});var n,o=r?r===!0||"number"==typeof r?a:r.effect||a:t;r=r||{},"number"==typeof r&&(r={duration:r}),n=!e.isEmptyObject(r),r.complete=s,r.delay&&i.delay(r.delay),n&&e.effects&&e.effects.effect[o]?i[t](r):o!==t&&i[o]?i[o](r.duration,r.easing,s):i.queue(function(a){e(this)[t](),s&&s.call(i[0]),a()})}}),e.widget;var h=!1;e(document).mouseup(function(){h=!1}),e.widget("ui.mouse",{version:"1.11.0-beta.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(a){return!0===e.data(a.target,t.widgetName+".preventClickEvent")?(e.removeData(a.target,t.widgetName+".preventClickEvent"),a.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!h){this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var a=this,i=1===t.which,r="string"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return i&&!r&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){a.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return a._mouseMove(e)},this._mouseUpDelegate=function(e){return a._mouseUp(e)},this.document.bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),h=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):t.which?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),h=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),function(){function t(e,t,a){return[parseFloat(e[0])*(c.test(e[0])?t/100:1),parseFloat(e[1])*(c.test(e[1])?a/100:1)]}function a(t,a){return parseInt(e.css(t,a),10)||0}function i(t){var a=t[0];return 9===a.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(a)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:a.preventDefault?{width:0,height:0,offset:{top:a.pageY,left:a.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var r,s,n=Math.max,o=Math.abs,d=Math.round,u=/left|center|right/,h=/top|center|bottom/,l=/[\+\-]\d+(\.[\d]+)?%?/,m=/^\w+/,c=/%$/,p=e.fn.position;e.position={scrollbarWidth:function(){if(void 0!==r)return r;var t,a,i=e("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),s=i.children()[0];return e("body").append(i),t=s.offsetWidth,i.css("overflow","scroll"),a=s.offsetWidth,t===a&&(a=i[0].clientWidth),i.remove(),r=t-a},getScrollInfo:function(t){var a=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),r="scroll"===a||"auto"===a&&t.width<t.element[0].scrollWidth,s="scroll"===i||"auto"===i&&t.height<t.element[0].scrollHeight;return{width:s?e.position.scrollbarWidth():0,height:r?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var a=e(t||window),i=e.isWindow(a[0]),r=!!a[0]&&9===a[0].nodeType;return{element:a,isWindow:i,isDocument:r,offset:a.offset()||{left:0,top:0},scrollLeft:a.scrollLeft(),scrollTop:a.scrollTop(),width:i?a.width():a.outerWidth(),height:i?a.height():a.outerHeight()}}},e.fn.position=function(r){if(!r||!r.of)return p.apply(this,arguments);r=e.extend({},r);var c,f,g,y,x,v,T=e(r.of),k=e.position.getWithinInfo(r.within),S=e.position.getScrollInfo(k),b=(r.collision||"flip").split(" "),N={};return v=i(T),T[0].preventDefault&&(r.at="left top"),f=v.width,g=v.height,y=v.offset,x=e.extend({},y),e.each(["my","at"],function(){var e,t,a=(r[this]||"").split(" ");1===a.length&&(a=u.test(a[0])?a.concat(["center"]):h.test(a[0])?["center"].concat(a):["center","center"]),a[0]=u.test(a[0])?a[0]:"center",a[1]=h.test(a[1])?a[1]:"center",e=l.exec(a[0]),t=l.exec(a[1]),N[this]=[e?e[0]:0,t?t[0]:0],r[this]=[m.exec(a[0])[0],m.exec(a[1])[0]]}),1===b.length&&(b[1]=b[0]),"right"===r.at[0]?x.left+=f:"center"===r.at[0]&&(x.left+=f/2),"bottom"===r.at[1]?x.top+=g:"center"===r.at[1]&&(x.top+=g/2),c=t(N.at,f,g),x.left+=c[0],x.top+=c[1],this.each(function(){var i,u,h=e(this),l=h.outerWidth(),m=h.outerHeight(),p=a(this,"marginLeft"),v=a(this,"marginTop"),M=l+p+a(this,"marginRight")+S.width,D=m+v+a(this,"marginBottom")+S.height,w=e.extend({},x),_=t(N.my,h.outerWidth(),h.outerHeight());"right"===r.my[0]?w.left-=l:"center"===r.my[0]&&(w.left-=l/2),"bottom"===r.my[1]?w.top-=m:"center"===r.my[1]&&(w.top-=m/2),w.left+=_[0],w.top+=_[1],s||(w.left=d(w.left),w.top=d(w.top)),i={marginLeft:p,marginTop:v},e.each(["left","top"],function(t,a){e.ui.position[b[t]]&&e.ui.position[b[t]][a](w,{targetWidth:f,targetHeight:g,elemWidth:l,elemHeight:m,collisionPosition:i,collisionWidth:M,collisionHeight:D,offset:[c[0]+_[0],c[1]+_[1]],my:r.my,at:r.at,within:k,elem:h})}),r.using&&(u=function(e){var t=y.left-w.left,a=t+f-l,i=y.top-w.top,s=i+g-m,d={target:{element:T,left:y.left,top:y.top,width:f,height:g},element:{element:h,left:w.left,top:w.top,width:l,height:m},horizontal:0>a?"left":t>0?"right":"center",vertical:0>s?"top":i>0?"bottom":"middle"};l>f&&f>o(t+a)&&(d.horizontal="center"),m>g&&g>o(i+s)&&(d.vertical="middle"),d.important=n(o(t),o(a))>n(o(i),o(s))?"horizontal":"vertical",r.using.call(this,e,d)}),h.offset(e.extend(w,{using:u}))})},e.ui.position={fit:{left:function(e,t){var a,i=t.within,r=i.isWindow?i.scrollLeft:i.offset.left,s=i.width,o=e.left-t.collisionPosition.marginLeft,d=r-o,u=o+t.collisionWidth-s-r;t.collisionWidth>s?d>0&&0>=u?(a=e.left+d+t.collisionWidth-s-r,e.left+=d-a):e.left=u>0&&0>=d?r:d>u?r+s-t.collisionWidth:r:d>0?e.left+=d:u>0?e.left-=u:e.left=n(e.left-o,e.left)},top:function(e,t){var a,i=t.within,r=i.isWindow?i.scrollTop:i.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,d=r-o,u=o+t.collisionHeight-s-r;t.collisionHeight>s?d>0&&0>=u?(a=e.top+d+t.collisionHeight-s-r,e.top+=d-a):e.top=u>0&&0>=d?r:d>u?r+s-t.collisionHeight:r:d>0?e.top+=d:u>0?e.top-=u:e.top=n(e.top-o,e.top)}},flip:{left:function(e,t){var a,i,r=t.within,s=r.offset.left+r.scrollLeft,n=r.width,d=r.isWindow?r.scrollLeft:r.offset.left,u=e.left-t.collisionPosition.marginLeft,h=u-d,l=u+t.collisionWidth-n-d,m="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,c="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,p=-2*t.offset[0];0>h?(a=e.left+m+c+p+t.collisionWidth-n-s,(0>a||o(h)>a)&&(e.left+=m+c+p)):l>0&&(i=e.left-t.collisionPosition.marginLeft+m+c+p-d,(i>0||l>o(i))&&(e.left+=m+c+p))},top:function(e,t){var a,i,r=t.within,s=r.offset.top+r.scrollTop,n=r.height,d=r.isWindow?r.scrollTop:r.offset.top,u=e.top-t.collisionPosition.marginTop,h=u-d,l=u+t.collisionHeight-n-d,m="top"===t.my[1],c=m?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,p="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,f=-2*t.offset[1];0>h?(i=e.top+c+p+f+t.collisionHeight-n-s,e.top+c+p+f>h&&(0>i||o(h)>i)&&(e.top+=c+p+f)):l>0&&(a=e.top-t.collisionPosition.marginTop+c+p+f-d,e.top+c+p+f>l&&(a>0||l>o(a))&&(e.top+=c+p+f))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,a,i,r,n,o=document.getElementsByTagName("body")[0],d=document.createElement("div");t=document.createElement(o?"div":"body"),i={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&e.extend(i,{position:"absolute",left:"-1000px",top:"-1000px"});for(n in i)t.style[n]=i[n];t.appendChild(d),a=o||document.documentElement,a.insertBefore(t,a.firstChild),d.style.cssText="position: absolute; left: 10.7432222px;",r=e(d).offset().left,s=r>10&&11>r,t.innerHTML="",a.removeChild(t)}()}(),e.ui.position,e.widget("ui.draggable",e.ui.mouse,{version:"1.11.0-beta.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),"handle"===e&&this._setHandleClassName()},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var a=this.document[0],i=this.options;try{a.activeElement&&"body"!==a.activeElement.nodeName.toLowerCase()&&e(a.activeElement).blur()}catch(r){}return this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){e("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var a=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!a.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,a){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!a){var i=this._uiHash();if(this._trigger("drag",t,i)===!1)return this._mouseUp({}),!1;this.position=i.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var a=this,i=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(i=e.ui.ddmanager.drop(this,t)),this.dropped&&(i=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!i||"valid"===this.options.revert&&i||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,i)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){a._trigger("stop",t)!==!1&&a._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this._removeHandleClassName(),e(this.options.handle||this.element).addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.element.find(".ui-draggable-handle").addBack().removeClass("ui-draggable-handle")},_createHelper:function(t){var a=this.options,i=e.isFunction(a.helper)?e(a.helper.apply(this.element[0],[t])):"clone"===a.helper?this.element.clone().removeAttr("id"):this.element;return i.parents("body").length||i.appendTo("parent"===a.appendTo?this.element[0].parentNode:a.appendTo),i[0]===this.element[0]||/(fixed|absolute)/.test(i.css("position"))||i.css("position","absolute"),i},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),a=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==a&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,a,i,r=this.options,s=this.document[0];return this.relative_container=null,r.containment?"window"===r.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||s.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===r.containment?(this.containment=[0,0,e(s).width()-this.helperProportions.width-this.margins.left,(e(s).height()||s.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):r.containment.constructor===Array?(this.containment=r.containment,void 0):("parent"===r.containment&&(r.containment=this.helper[0].parentNode),a=e(r.containment),i=a[0],i&&(t="hidden"!==a.css("overflow"),this.containment=[(parseInt(a.css("borderLeftWidth"),10)||0)+(parseInt(a.css("paddingLeft"),10)||0),(parseInt(a.css("borderTopWidth"),10)||0)+(parseInt(a.css("paddingTop"),10)||0),(t?Math.max(i.scrollWidth,i.offsetWidth):i.offsetWidth)-(parseInt(a.css("borderRightWidth"),10)||0)-(parseInt(a.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(i.scrollHeight,i.offsetHeight):i.offsetHeight)-(parseInt(a.css("borderBottomWidth"),10)||0)-(parseInt(a.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=a),void 0):(this.containment=null,void 0)},_convertPositionTo:function(e,t){t||(t=this.position);var a="absolute"===e?1:-1,i=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*a+this.offset.parent.top*a-("fixed"===this.cssPosition?-this.offset.scroll.top:i?0:this.offset.scroll.top)*a,left:t.left+this.offset.relative.left*a+this.offset.parent.left*a-("fixed"===this.cssPosition?-this.offset.scroll.left:i?0:this.offset.scroll.left)*a}},_generatePosition:function(e,t){var a,i,r,s,n=this.options,o=this._isRootNode(this.scrollParent[0]),d=e.pageX,u=e.pageY;return o&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relative_container?(i=this.relative_container.offset(),a=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]):a=this.containment,e.pageX-this.offset.click.left<a[0]&&(d=a[0]+this.offset.click.left),e.pageY-this.offset.click.top<a[1]&&(u=a[1]+this.offset.click.top),e.pageX-this.offset.click.left>a[2]&&(d=a[2]+this.offset.click.left),e.pageY-this.offset.click.top>a[3]&&(u=a[3]+this.offset.click.top)),n.grid&&(r=n.grid[1]?this.originalPageY+Math.round((u-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY,u=a?r-this.offset.click.top>=a[1]||r-this.offset.click.top>a[3]?r:r-this.offset.click.top>=a[1]?r-n.grid[1]:r+n.grid[1]:r,s=n.grid[0]?this.originalPageX+Math.round((d-this.originalPageX)/n.grid[0])*n.grid[0]:this.originalPageX,d=a?s-this.offset.click.left>=a[0]||s-this.offset.click.left>a[2]?s:s-this.offset.click.left>=a[0]?s-n.grid[0]:s+n.grid[0]:s),"y"===n.axis&&(d=this.originalPageX),"x"===n.axis&&(u=this.originalPageY)),{top:u-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:o?0:this.offset.scroll.top),left:d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:o?0:this.offset.scroll.left)}
+},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(t,a,i){return i=i||this._uiHash(),e.ui.plugin.call(this,t,[a,i,this],!0),"drag"===t&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,a,i)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,a,i){var r=i.options,s=e.extend({},a,{item:i.element});i.sortables=[],e(r.connectToSortable).each(function(){var a=e(this).sortable("instance");a&&!a.options.disabled&&(i.sortables.push({instance:a,shouldRevert:a.options.revert}),a.refreshPositions(),a._trigger("activate",t,s))})},stop:function(t,a,i){var r=e.extend({},a,{item:i.element});e.each(i.sortables,function(){this.instance.isOver?(this.instance.isOver=0,i.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,"original"===i.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,r))})},drag:function(t,a,i){var r=this;e.each(i.sortables,function(){var s=!1,n=this;this.instance.positionAbs=i.positionAbs,this.instance.helperProportions=i.helperProportions,this.instance.offset.click=i.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(s=!0,e.each(i.sortables,function(){return this.instance.positionAbs=i.positionAbs,this.instance.helperProportions=i.helperProportions,this.instance.offset.click=i.offset.click,this!==n&&this.instance._intersectsWith(this.instance.containerCache)&&e.contains(n.instance.element[0],this.instance.element[0])&&(s=!1),s})),s?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(r).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return a.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=i.offset.click.top,this.instance.offset.click.left=i.offset.click.left,this.instance.offset.parent.left-=i.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=i.offset.parent.top-this.instance.offset.parent.top,i._trigger("toSortable",t),i.dropped=this.instance.element,i.currentItem=i.element,this.instance.fromOutside=i),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),i._trigger("fromSortable",t),i.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,a,i){var r=e("body"),s=i.options;r.css("cursor")&&(s._cursor=r.css("cursor")),r.css("cursor",s.cursor)},stop:function(t,a,i){var r=i.options;r._cursor&&e("body").css("cursor",r._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,a,i){var r=e(a.helper),s=i.options;r.css("opacity")&&(s._opacity=r.css("opacity")),r.css("opacity",s.opacity)},stop:function(t,a,i){var r=i.options;r._opacity&&e(a.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(e,t,a){a.scrollParent[0]!==a.document[0]&&"HTML"!==a.scrollParent[0].tagName&&(a.overflowOffset=a.scrollParent.offset())},drag:function(t,a,i){var r=i.options,s=!1,n=i.document[0];i.scrollParent[0]!==n&&"HTML"!==i.scrollParent[0].tagName?(r.axis&&"x"===r.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-t.pageY<r.scrollSensitivity?i.scrollParent[0].scrollTop=s=i.scrollParent[0].scrollTop+r.scrollSpeed:t.pageY-i.overflowOffset.top<r.scrollSensitivity&&(i.scrollParent[0].scrollTop=s=i.scrollParent[0].scrollTop-r.scrollSpeed)),r.axis&&"y"===r.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-t.pageX<r.scrollSensitivity?i.scrollParent[0].scrollLeft=s=i.scrollParent[0].scrollLeft+r.scrollSpeed:t.pageX-i.overflowOffset.left<r.scrollSensitivity&&(i.scrollParent[0].scrollLeft=s=i.scrollParent[0].scrollLeft-r.scrollSpeed))):(r.axis&&"x"===r.axis||(t.pageY-e(n).scrollTop()<r.scrollSensitivity?s=e(n).scrollTop(e(n).scrollTop()-r.scrollSpeed):e(window).height()-(t.pageY-e(n).scrollTop())<r.scrollSensitivity&&(s=e(n).scrollTop(e(n).scrollTop()+r.scrollSpeed))),r.axis&&"y"===r.axis||(t.pageX-e(n).scrollLeft()<r.scrollSensitivity?s=e(n).scrollLeft(e(n).scrollLeft()-r.scrollSpeed):e(window).width()-(t.pageX-e(n).scrollLeft())<r.scrollSensitivity&&(s=e(n).scrollLeft(e(n).scrollLeft()+r.scrollSpeed)))),s!==!1&&e.ui.ddmanager&&!r.dropBehaviour&&e.ui.ddmanager.prepareOffsets(i,t)}}),e.ui.plugin.add("draggable","snap",{start:function(t,a,i){var r=i.options;i.snapElements=[],e(r.snap.constructor!==String?r.snap.items||":data(ui-draggable)":r.snap).each(function(){var t=e(this),a=t.offset();this!==i.element[0]&&i.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:a.top,left:a.left})})},drag:function(t,a,i){var r,s,n,o,d,u,h,l,m,c,p=i.options,f=p.snapTolerance,g=a.offset.left,y=g+i.helperProportions.width,x=a.offset.top,v=x+i.helperProportions.height;for(m=i.snapElements.length-1;m>=0;m--)d=i.snapElements[m].left,u=d+i.snapElements[m].width,h=i.snapElements[m].top,l=h+i.snapElements[m].height,d-f>y||g>u+f||h-f>v||x>l+f||!e.contains(i.snapElements[m].item.ownerDocument,i.snapElements[m].item)?(i.snapElements[m].snapping&&i.options.snap.release&&i.options.snap.release.call(i.element,t,e.extend(i._uiHash(),{snapItem:i.snapElements[m].item})),i.snapElements[m].snapping=!1):("inner"!==p.snapMode&&(r=f>=Math.abs(h-v),s=f>=Math.abs(l-x),n=f>=Math.abs(d-y),o=f>=Math.abs(u-g),r&&(a.position.top=i._convertPositionTo("relative",{top:h-i.helperProportions.height,left:0}).top-i.margins.top),s&&(a.position.top=i._convertPositionTo("relative",{top:l,left:0}).top-i.margins.top),n&&(a.position.left=i._convertPositionTo("relative",{top:0,left:d-i.helperProportions.width}).left-i.margins.left),o&&(a.position.left=i._convertPositionTo("relative",{top:0,left:u}).left-i.margins.left)),c=r||s||n||o,"outer"!==p.snapMode&&(r=f>=Math.abs(h-x),s=f>=Math.abs(l-v),n=f>=Math.abs(d-g),o=f>=Math.abs(u-y),r&&(a.position.top=i._convertPositionTo("relative",{top:h,left:0}).top-i.margins.top),s&&(a.position.top=i._convertPositionTo("relative",{top:l-i.helperProportions.height,left:0}).top-i.margins.top),n&&(a.position.left=i._convertPositionTo("relative",{top:0,left:d}).left-i.margins.left),o&&(a.position.left=i._convertPositionTo("relative",{top:0,left:u-i.helperProportions.width}).left-i.margins.left)),!i.snapElements[m].snapping&&(r||s||n||o||c)&&i.options.snap.snap&&i.options.snap.snap.call(i.element,t,e.extend(i._uiHash(),{snapItem:i.snapElements[m].item})),i.snapElements[m].snapping=r||s||n||o||c)}}),e.ui.plugin.add("draggable","stack",{start:function(t,a,i){var r,s=i.options,n=e.makeArray(e(s.stack)).sort(function(t,a){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(a).css("zIndex"),10)||0)});n.length&&(r=parseInt(e(n[0]).css("zIndex"),10)||0,e(n).each(function(t){e(this).css("zIndex",r+t)}),this.css("zIndex",r+n.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,a,i){var r=e(a.helper),s=i.options;r.css("zIndex")&&(s._zIndex=r.css("zIndex")),r.css("zIndex",s.zIndex)},stop:function(t,a,i){var r=i.options;r._zIndex&&e(a.helper).css("zIndex",r._zIndex)}}),e.ui.draggable,e.widget("ui.droppable",{version:"1.11.0-beta.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,a=this.options,i=a.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(i)?i:function(e){return e.is(i)},this.proportions=function(){return arguments.length?(t=arguments[0],void 0):t?t:t={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(a.scope),a.addClasses&&this.element.addClass("ui-droppable")},_addToManager:function(t){e.ui.ddmanager.droppables[t]=e.ui.ddmanager.droppables[t]||[],e.ui.ddmanager.droppables[t].push(this)},_splice:function(e){for(var t=0;e.length>t;t++)e[t]===this&&e.splice(t,1)},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];this._splice(t),this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,a){if("accept"===t)this.accept=e.isFunction(a)?a:function(e){return e.is(a)};else if("scope"===t){var i=e.ui.ddmanager.droppables[this.options.scope];this._splice(i),this._addToManager(a)}this._super(t,a)},_activate:function(t){var a=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),a&&this._trigger("activate",t,this.ui(a))},_deactivate:function(t){var a=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),a&&this._trigger("deactivate",t,this.ui(a))},_over:function(t){var a=e.ui.ddmanager.current;a&&(a.currentItem||a.element)[0]!==this.element[0]&&this.accept.call(this.element[0],a.currentItem||a.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(a)))},_out:function(t){var a=e.ui.ddmanager.current;a&&(a.currentItem||a.element)[0]!==this.element[0]&&this.accept.call(this.element[0],a.currentItem||a.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(a)))},_drop:function(t,a){var i=a||e.ui.ddmanager.current,r=!1;return i&&(i.currentItem||i.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var t=e(this).droppable("instance");return t.options.greedy&&!t.options.disabled&&t.options.scope===i.options.scope&&t.accept.call(t.element[0],i.currentItem||i.element)&&e.ui.intersect(i,e.extend(t,{offset:t.element.offset()}),t.options.tolerance)?(r=!0,!1):void 0}),r?!1:this.accept.call(this.element[0],i.currentItem||i.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(i)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(){function e(e,t,a){return e>=t&&t+a>e}return function(t,a,i){if(!a.offset)return!1;var r,s,n=(t.positionAbs||t.position.absolute).left,o=(t.positionAbs||t.position.absolute).top,d=n+t.helperProportions.width,u=o+t.helperProportions.height,h=a.offset.left,l=a.offset.top,m=h+a.proportions().width,c=l+a.proportions().height;switch(i){case"fit":return n>=h&&m>=d&&o>=l&&c>=u;case"intersect":return n+t.helperProportions.width/2>h&&m>d-t.helperProportions.width/2&&o+t.helperProportions.height/2>l&&c>u-t.helperProportions.height/2;case"pointer":return r=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,s=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,e(s,l,a.proportions().height)&&e(r,h,a.proportions().width);case"touch":return(o>=l&&c>=o||u>=l&&c>=u||l>o&&u>c)&&(n>=h&&m>=n||d>=h&&m>=d||h>n&&d>m);default:return!1}}}(),e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,a){var i,r,s=e.ui.ddmanager.droppables[t.options.scope]||[],n=a?a.type:null,o=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(i=0;s.length>i;i++)if(!(s[i].options.disabled||t&&!s[i].accept.call(s[i].element[0],t.currentItem||t.element))){for(r=0;o.length>r;r++)if(o[r]===s[i].element[0]){s[i].proportions().height=0;continue e}s[i].visible="none"!==s[i].element.css("display"),s[i].visible&&("mousedown"===n&&s[i]._activate.call(s[i],a),s[i].offset=s[i].element.offset(),s[i].proportions({width:s[i].element[0].offsetWidth,height:s[i].element[0].offsetHeight}))}},drop:function(t,a){var i=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(i=this._drop.call(this,a)||i),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,a)))}),i},dragStart:function(t,a){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,a)})},drag:function(t,a){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,a),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var i,r,s,n=e.ui.intersect(t,this,this.options.tolerance),o=!n&&this.isover?"isout":n&&!this.isover?"isover":null;o&&(this.options.greedy&&(r=this.options.scope,s=this.element.parents(":data(ui-droppable)").filter(function(){return e(this).droppable("instance").options.scope===r}),s.length&&(i=e(s[0]).droppable("instance"),i.greedyChild="isover"===o)),i&&"isover"===o&&(i.isover=!1,i.isout=!0,i._out.call(i,a)),this[o]=!0,this["isout"===o?"isover":"isout"]=!1,this["isover"===o?"_over":"_out"].call(this,a),i&&"isout"===o&&(i.isout=!1,i.isover=!0,i._over.call(i,a)))}})},dragStop:function(t,a){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,a)}},e.ui.droppable,e.widget("ui.resizable",e.ui.mouse,{version:"1.11.0-beta.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(e){return parseInt(e,10)||0},_isNumber:function(e){return!isNaN(parseInt(e,10))},_hasScroll:function(t,a){if("hidden"===e(t).css("overflow"))return!1;var i=a&&"left"===a?"scrollLeft":"scrollTop",r=!1;return t[i]>0?!0:(t[i]=1,r=t[i]>0,t[i]=0,r)},_create:function(){var t,a,i,r,s,n=this,o=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!o.aspectRatio,aspectRatio:o.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:o.helper||o.ghost||o.animate?o.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=o.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},a=0;t.length>a;a++)i=e.trim(t[a]),s="ui-resizable-"+i,r=e("<div class='ui-resizable-handle "+s+"'></div>"),r.css({zIndex:o.zIndex}),"se"===i&&r.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[i]=".ui-resizable-"+i,this.element.append(r);this._renderAxis=function(t){var a,i,r,s;t=t||this.element;for(a in this.handles)this.handles[a].constructor===String&&(this.handles[a]=this.element.children(this.handles[a]).first().show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(i=e(this.handles[a],this.element),s=/sw|ne|nw|se|n|s/.test(a)?i.outerHeight():i.outerWidth(),r=["padding",/ne|nw|n/.test(a)?"Top":/se|sw|s/.test(a)?"Bottom":/^e$/.test(a)?"Right":"Left"].join(""),t.css(r,s),this._proportionallyResize()),e(this.handles[a]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){n.resizing||(this.className&&(r=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),n.axis=r&&r[1]?r[1]:"se")}),o.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){o.disabled||(e(this).removeClass("ui-resizable-autohide"),n._handles.show())}).mouseleave(function(){o.disabled||n.resizing||(e(this).addClass("ui-resizable-autohide"),n._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,a=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(a(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),a(this.originalElement),this},_mouseCapture:function(t){var a,i,r=!1;for(a in this.handles)i=e(this.handles[a])[0],(i===t.target||e.contains(i,t.target))&&(r=!0);return!this.options.disabled&&r},_mouseStart:function(t){var a,i,r,s=this.options,n=this.element;return this.resizing=!0,this._renderProxy(),a=this._num(this.helper.css("left")),i=this._num(this.helper.css("top")),s.containment&&(a+=e(s.containment).scrollLeft()||0,i+=e(s.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:a,top:i},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:n.width(),height:n.height()},this.originalSize=this._helper?{width:n.outerWidth(),height:n.outerHeight()}:{width:n.width(),height:n.height()},this.originalPosition={left:a,top:i},this.sizeDiff={width:n.outerWidth()-n.width(),height:n.outerHeight()-n.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof s.aspectRatio?s.aspectRatio:this.originalSize.width/this.originalSize.height||1,r=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===r?this.axis+"-resize":r),n.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var a,i=this.helper,r={},s=this.originalMousePosition,n=this.axis,o=t.pageX-s.left||0,d=t.pageY-s.top||0,u=this._change[n];return this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height},u?(a=u.apply(this,[t,o,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(a=this._updateRatio(a,t)),a=this._respectSize(a,t),this._updateCache(a),this._propagate("resize",t),this.position.top!==this.prevPosition.top&&(r.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(r.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(r.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(r.height=this.size.height+"px"),i.css(r),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(r)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var a,i,r,s,n,o,d,u=this.options,h=this;return this._helper&&(a=this._proportionallyResizeElements,i=a.length&&/textarea/i.test(a[0].nodeName),r=i&&this._hasScroll(a[0],"left")?0:h.sizeDiff.height,s=i?0:h.sizeDiff.width,n={width:h.helper.width()-s,height:h.helper.height()-r},o=parseInt(h.element.css("left"),10)+(h.position.left-h.originalPosition.left)||null,d=parseInt(h.element.css("top"),10)+(h.position.top-h.originalPosition.top)||null,u.animate||this.element.css(e.extend(n,{top:d,left:o})),h.helper.height(h.size.height),h.helper.width(h.size.width),this._helper&&!u.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,a,i,r,s,n=this.options;s={minWidth:this._isNumber(n.minWidth)?n.minWidth:0,maxWidth:this._isNumber(n.maxWidth)?n.maxWidth:1/0,minHeight:this._isNumber(n.minHeight)?n.minHeight:0,maxHeight:this._isNumber(n.maxHeight)?n.maxHeight:1/0},(this._aspectRatio||e)&&(t=s.minHeight*this.aspectRatio,i=s.minWidth/this.aspectRatio,a=s.maxHeight*this.aspectRatio,r=s.maxWidth/this.aspectRatio,t>s.minWidth&&(s.minWidth=t),i>s.minHeight&&(s.minHeight=i),s.maxWidth>a&&(s.maxWidth=a),s.maxHeight>r&&(s.maxHeight=r)),this._vBoundaries=s},_updateCache:function(e){this.offset=this.helper.offset(),this._isNumber(e.left)&&(this.position.left=e.left),this._isNumber(e.top)&&(this.position.top=e.top),this._isNumber(e.height)&&(this.size.height=e.height),this._isNumber(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,a=this.size,i=this.axis;return this._isNumber(e.height)?e.width=e.height*this.aspectRatio:this._isNumber(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===i&&(e.left=t.left+(a.width-e.width),e.top=null),"nw"===i&&(e.top=t.top+(a.height-e.height),e.left=t.left+(a.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,a=this.axis,i=this._isNumber(e.width)&&t.maxWidth&&t.maxWidth<e.width,r=this._isNumber(e.height)&&t.maxHeight&&t.maxHeight<e.height,s=this._isNumber(e.width)&&t.minWidth&&t.minWidth>e.width,n=this._isNumber(e.height)&&t.minHeight&&t.minHeight>e.height,o=this.originalPosition.left+this.originalSize.width,d=this.position.top+this.size.height,u=/sw|nw|w/.test(a),h=/nw|ne|n/.test(a);return s&&(e.width=t.minWidth),n&&(e.height=t.minHeight),i&&(e.width=t.maxWidth),r&&(e.height=t.maxHeight),s&&u&&(e.left=o-t.minWidth),i&&u&&(e.left=o-t.maxWidth),n&&h&&(e.top=d-t.minHeight),r&&h&&(e.top=d-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,a,i,r,s=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(r=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],a=[r.css("borderTopWidth"),r.css("borderRightWidth"),r.css("borderBottomWidth"),r.css("borderLeftWidth")],i=[r.css("paddingTop"),r.css("paddingRight"),r.css("paddingBottom"),r.css("paddingLeft")],t=0;a.length>t;t++)this.borderDif[t]=(parseInt(a[t],10)||0)+(parseInt(i[t],10)||0);r.css({height:s.height()-this.borderDif[0]-this.borderDif[2]||0,width:s.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,a=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++a.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var a=this.originalSize,i=this.originalPosition;return{left:i.left+t,width:a.width-t}},n:function(e,t,a){var i=this.originalSize,r=this.originalPosition;return{top:r.top+a,height:i.height-a}},s:function(e,t,a){return{height:this.originalSize.height+a}},se:function(t,a,i){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,a,i]))},sw:function(t,a,i){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,a,i]))},ne:function(t,a,i){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,a,i]))},nw:function(t,a,i){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,a,i]))}},_propagate:function(t,a){e.ui.plugin.call(this,t,[a,this.ui()]),"resize"!==t&&this._trigger(t,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition,prevSize:this.prevSize,prevPosition:this.prevPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var a=e(this).resizable("instance"),i=a.options,r=a._proportionallyResizeElements,s=r.length&&/textarea/i.test(r[0].nodeName),n=s&&a._hasScroll(r[0],"left")?0:a.sizeDiff.height,o=s?0:a.sizeDiff.width,d={width:a.size.width-o,height:a.size.height-n},u=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null,h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(d,h&&u?{top:h,left:u}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};r&&r.length&&e(r[0]).css({width:i.width,height:i.height}),a._updateCache(i),a._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,a,i,r,s,n,o,d=e(this).resizable("instance"),u=d.options,h=d.element,l=u.containment,m=l instanceof e?l.get(0):/parent/.test(l)?h.parent().get(0):l;m&&(d.containerElement=e(m),/document/.test(l)||l===document?(d.containerOffset={left:0,top:0},d.containerPosition={left:0,top:0},d.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(m),a=[],e(["Top","Right","Left","Bottom"]).each(function(e,i){a[e]=d._num(t.css("padding"+i))}),d.containerOffset=t.offset(),d.containerPosition=t.position(),d.containerSize={height:t.innerHeight()-a[3],width:t.innerWidth()-a[1]},i=d.containerOffset,r=d.containerSize.height,s=d.containerSize.width,n=d._hasScroll(m,"left")?m.scrollWidth:s,o=d._hasScroll(m)?m.scrollHeight:r,d.parentData={element:m,left:i.left,top:i.top,width:n,height:o}))},resize:function(t,a){var i,r,s,n,o=e(this).resizable("instance"),d=o.options,u=o.containerOffset,h=o.position,l=o._aspectRatio||t.shiftKey,m={top:0,left:0},c=o.containerElement,p=!0;c[0]!==document&&/static/.test(c.css("position"))&&(m=u),h.left<(o._helper?u.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-u.left:o.position.left-m.left),l&&(o.size.height=o.size.width/o.aspectRatio,p=!1),o.position.left=d.helper?u.left:0),h.top<(o._helper?u.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-u.top:o.position.top),l&&(o.size.width=o.size.height*o.aspectRatio,p=!1),o.position.top=o._helper?u.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-m.left:o.offset.left-u.left)+o.sizeDiff.width),r=Math.abs((o._helper?o.offset.top-m.top:o.offset.top-u.top)+o.sizeDiff.height),s=o.containerElement.get(0)===o.element.parent().get(0),n=/relative|absolute/.test(o.containerElement.css("position")),s&&n&&(i-=Math.abs(o.parentData.left)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,l&&(o.size.height=o.size.width/o.aspectRatio,p=!1)),r+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-r,l&&(o.size.width=o.size.height*o.aspectRatio,p=!1)),p||(o.position.left=a.prevPosition.left,o.position.top=a.prevPosition.top,o.size.width=a.prevSize.width,o.size.height=a.prevSize.height)},stop:function(){var t=e(this).resizable("instance"),a=t.options,i=t.containerOffset,r=t.containerPosition,s=t.containerElement,n=e(t.helper),o=n.offset(),d=n.outerWidth()-t.sizeDiff.width,u=n.outerHeight()-t.sizeDiff.height;t._helper&&!a.animate&&/relative/.test(s.css("position"))&&e(this).css({left:o.left-r.left-i.left,width:d,height:u}),t._helper&&!a.animate&&/static/.test(s.css("position"))&&e(this).css({left:o.left-r.left-i.left,width:d,height:u})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).resizable("instance"),a=t.options,i=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof a.alsoResize||a.alsoResize.parentNode?i(a.alsoResize):a.alsoResize.length?(a.alsoResize=a.alsoResize[0],i(a.alsoResize)):e.each(a.alsoResize,function(e){i(e)})},resize:function(t,a){var i=e(this).resizable("instance"),r=i.options,s=i.originalSize,n=i.originalPosition,o={height:i.size.height-s.height||0,width:i.size.width-s.width||0,top:i.position.top-n.top||0,left:i.position.left-n.left||0},d=function(t,i){e(t).each(function(){var t=e(this),r=e(this).data("ui-resizable-alsoresize"),s={},n=i&&i.length?i:t.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(n,function(e,t){var a=(r[t]||0)+(o[t]||0);a&&a>=0&&(s[t]=a||null)}),t.css(s)})};"object"!=typeof r.alsoResize||r.alsoResize.nodeType?d(r.alsoResize):e.each(r.alsoResize,function(e,t){d(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).resizable("instance"),a=t.options,i=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof a.ghost?a.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).resizable("instance"),a=t.options,i=t.size,r=t.originalSize,s=t.originalPosition,n=t.axis,o="number"==typeof a.grid?[a.grid,a.grid]:a.grid,d=o[0]||1,u=o[1]||1,h=Math.round((i.width-r.width)/d)*d,l=Math.round((i.height-r.height)/u)*u,m=r.width+h,c=r.height+l,p=a.maxWidth&&m>a.maxWidth,f=a.maxHeight&&c>a.maxHeight,g=a.minWidth&&a.minWidth>m,y=a.minHeight&&a.minHeight>c;a.grid=o,g&&(m+=d),y&&(c+=u),p&&(m-=d),f&&(c-=u),/^(se|s|e)$/.test(n)?(t.size.width=m,t.size.height=c):/^(ne)$/.test(n)?(t.size.width=m,t.size.height=c,t.position.top=s.top-l):/^(sw)$/.test(n)?(t.size.width=m,t.size.height=c,t.position.left=s.left-h):(c-u>0?(t.size.height=c,t.position.top=s.top-l):(t.size.height=u,t.position.top=s.top+r.height-u),m-d>0?(t.size.width=m,t.position.left=s.left-h):(t.size.width=d,t.position.left=s.left+r.width-d))}}),e.ui.resizable,e.widget("ui.selectable",e.ui.mouse,{version:"1.11.0-beta.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,a=this;
+this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(a.options.filter,a.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),a=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:a.left,top:a.top,right:a.left+t.outerWidth(),bottom:a.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var a=this,i=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(i.filter,this.element[0]),this._trigger("start",t),e(i.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),i.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var i=e.data(this,"selectable-item");i.startselected=!0,t.metaKey||t.ctrlKey||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,a._trigger("unselecting",t,{unselecting:i.element}))}),e(t.target).parents().addBack().each(function(){var i,r=e.data(this,"selectable-item");return r?(i=!t.metaKey&&!t.ctrlKey||!r.$element.hasClass("ui-selected"),r.$element.removeClass(i?"ui-unselecting":"ui-selected").addClass(i?"ui-selecting":"ui-unselecting"),r.unselecting=!i,r.selecting=i,r.selected=i,i?a._trigger("selecting",t,{selecting:r.element}):a._trigger("unselecting",t,{unselecting:r.element}),!1):void 0}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var a,i=this,r=this.options,s=this.opos[0],n=this.opos[1],o=t.pageX,d=t.pageY;return s>o&&(a=o,o=s,s=a),n>d&&(a=d,d=n,n=a),this.helper.css({left:s,top:n,width:o-s,height:d-n}),this.selectees.each(function(){var a=e.data(this,"selectable-item"),u=!1;a&&a.element!==i.element[0]&&("touch"===r.tolerance?u=!(a.left>o||s>a.right||a.top>d||n>a.bottom):"fit"===r.tolerance&&(u=a.left>s&&o>a.right&&a.top>n&&d>a.bottom),u?(a.selected&&(a.$element.removeClass("ui-selected"),a.selected=!1),a.unselecting&&(a.$element.removeClass("ui-unselecting"),a.unselecting=!1),a.selecting||(a.$element.addClass("ui-selecting"),a.selecting=!0,i._trigger("selecting",t,{selecting:a.element}))):(a.selecting&&((t.metaKey||t.ctrlKey)&&a.startselected?(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.$element.addClass("ui-selected"),a.selected=!0):(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.startselected&&(a.$element.addClass("ui-unselecting"),a.unselecting=!0),i._trigger("unselecting",t,{unselecting:a.element}))),a.selected&&(t.metaKey||t.ctrlKey||a.startselected||(a.$element.removeClass("ui-selected"),a.selected=!1,a.$element.addClass("ui-unselecting"),a.unselecting=!0,i._trigger("unselecting",t,{unselecting:a.element})))))}),!1}},_mouseStop:function(t){var a=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var i=e.data(this,"selectable-item");i.$element.removeClass("ui-unselecting"),i.unselecting=!1,i.startselected=!1,a._trigger("unselected",t,{unselected:i.element})}),e(".ui-selecting",this.element[0]).each(function(){var i=e.data(this,"selectable-item");i.$element.removeClass("ui-selecting").addClass("ui-selected"),i.selecting=!1,i.selected=!0,i.startselected=!0,a._trigger("selected",t,{selected:i.element})}),this._trigger("stop",t),this.helper.remove(),!1}}),e.widget("ui.sortable",e.ui.mouse,{version:"1.11.0-beta.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(e,t,a){return e>=t&&t+a>e},_isFloating:function(e){return/left|right/.test(e.css("float"))||/inline|table-cell/.test(e.css("display"))},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===e.axis||this._isFloating(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(e,t){this._super(e,t),"handle"===e&&this._setHandleClassName()},_setHandleClassName:function(){this.element.find(".ui-sortable-handle").removeClass("ui-sortable-handle"),e.each(this.items,function(){(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item).addClass("ui-sortable-handle")})},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").find(".ui-sortable-handle").removeClass("ui-sortable-handle"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(t,a){var i=null,r=!1,s=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(t),e(t.target).parents().each(function(){return e.data(this,s.widgetName+"-item")===s?(i=e(this),!1):void 0}),e.data(t.target,s.widgetName+"-item")===s&&(i=e(t.target)),i?!this.options.handle||a||(e(this.options.handle,i).find("*").addBack().each(function(){this===t.target&&(r=!0)}),r)?(this.currentItem=i,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(t,a,i){var r,s,n=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),n.containment&&this._setContainment(),n.cursor&&"auto"!==n.cursor&&(s=this.document.find("body"),this.storedCursor=s.css("cursor"),s.css("cursor",n.cursor),this.storedStylesheet=e("<style>*{ cursor: "+n.cursor+" !important; }</style>").appendTo(s)),n.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",n.opacity)),n.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",n.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!i)for(r=this.containers.length-1;r>=0;r--)this.containers[r]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var a,i,r,s,n=this.options,o=!1;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<n.scrollSensitivity?this.scrollParent[0].scrollTop=o=this.scrollParent[0].scrollTop+n.scrollSpeed:t.pageY-this.overflowOffset.top<n.scrollSensitivity&&(this.scrollParent[0].scrollTop=o=this.scrollParent[0].scrollTop-n.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<n.scrollSensitivity?this.scrollParent[0].scrollLeft=o=this.scrollParent[0].scrollLeft+n.scrollSpeed:t.pageX-this.overflowOffset.left<n.scrollSensitivity&&(this.scrollParent[0].scrollLeft=o=this.scrollParent[0].scrollLeft-n.scrollSpeed)):(t.pageY-e(document).scrollTop()<n.scrollSensitivity?o=e(document).scrollTop(e(document).scrollTop()-n.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<n.scrollSensitivity&&(o=e(document).scrollTop(e(document).scrollTop()+n.scrollSpeed)),t.pageX-e(document).scrollLeft()<n.scrollSensitivity?o=e(document).scrollLeft(e(document).scrollLeft()-n.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<n.scrollSensitivity&&(o=e(document).scrollLeft(e(document).scrollLeft()+n.scrollSpeed))),o!==!1&&e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),a=this.items.length-1;a>=0;a--)if(i=this.items[a],r=i.item[0],s=this._intersectsWithPointer(i),s&&i.instance===this.currentContainer&&r!==this.currentItem[0]&&this.placeholder[1===s?"next":"prev"]()[0]!==r&&!e.contains(this.placeholder[0],r)&&("semi-dynamic"===this.options.type?!e.contains(this.element[0],r):!0)){if(this.direction=1===s?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(i))break;this._rearrange(t,i),this._trigger("change",t,this._uiHash());break}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,a){if(t){if(e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t),this.options.revert){var i=this,r=this.placeholder.offset(),s=this.options.axis,n={};s&&"x"!==s||(n.left=r.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),s&&"y"!==s||(n.top=r.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,e(this.helper).animate(n,parseInt(this.options.revert,10)||500,function(){i._clear(t)})}else this._clear(t,a);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var a=this._getItemsAsjQuery(t&&t.connected),i=[];return t=t||{},e(a).each(function(){var a=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);a&&i.push((t.key||a[1]+"[]")+"="+(t.key&&t.expression?a[1]:a[2]))}),!i.length&&t.key&&i.push(t.key+"="),i.join("&")},toArray:function(t){var a=this._getItemsAsjQuery(t&&t.connected),i=[];return t=t||{},a.each(function(){i.push(e(t.item||this).attr(t.attribute||"id")||"")}),i},_intersectsWith:function(e){var t=this.positionAbs.left,a=t+this.helperProportions.width,i=this.positionAbs.top,r=i+this.helperProportions.height,s=e.left,n=s+e.width,o=e.top,d=o+e.height,u=this.offset.click.top,h=this.offset.click.left,l="x"===this.options.axis||i+u>o&&d>i+u,m="y"===this.options.axis||t+h>s&&n>t+h,c=l&&m;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?c:t+this.helperProportions.width/2>s&&n>a-this.helperProportions.width/2&&i+this.helperProportions.height/2>o&&d>r-this.helperProportions.height/2},_intersectsWithPointer:function(e){var t="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top,e.height),a="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left,e.width),i=t&&a,r=this._getDragVerticalDirection(),s=this._getDragHorizontalDirection();return i?this.floating?s&&"right"===s||"down"===r?2:1:r&&("down"===r?2:1):!1},_intersectsWithSides:function(e){var t=this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),a=this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),i=this._getDragVerticalDirection(),r=this._getDragHorizontalDirection();return this.floating&&r?"right"===r&&a||"left"===r&&!a:i&&("down"===i&&t||"up"===i&&!t)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return 0!==e&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return 0!==e&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){function a(){o.push(this)}var i,r,s,n,o=[],d=[],u=this._connectWith();if(u&&t)for(i=u.length-1;i>=0;i--)for(s=e(u[i]),r=s.length-1;r>=0;r--)n=e.data(s[r],this.widgetFullName),n&&n!==this&&!n.options.disabled&&d.push([e.isFunction(n.options.items)?n.options.items.call(n.element):e(n.options.items,n.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),n]);for(d.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),i=d.length-1;i>=0;i--)d[i][0].each(a);return e(o)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var a=0;t.length>a;a++)if(t[a]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var a,i,r,s,n,o,d,u,h=this.items,l=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],m=this._connectWith();if(m&&this.ready)for(a=m.length-1;a>=0;a--)for(r=e(m[a]),i=r.length-1;i>=0;i--)s=e.data(r[i],this.widgetFullName),s&&s!==this&&!s.options.disabled&&(l.push([e.isFunction(s.options.items)?s.options.items.call(s.element[0],t,{item:this.currentItem}):e(s.options.items,s.element),s]),this.containers.push(s));for(a=l.length-1;a>=0;a--)for(n=l[a][1],o=l[a][0],i=0,u=o.length;u>i;i++)d=e(o[i]),d.data(this.widgetName+"-item",n),h.push({item:d,instance:n,width:0,height:0,left:0,top:0})},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var a,i,r,s;for(a=this.items.length-1;a>=0;a--)i=this.items[a],i.instance!==this.currentContainer&&this.currentContainer&&i.item[0]!==this.currentItem[0]||(r=this.options.toleranceElement?e(this.options.toleranceElement,i.item):i.item,t||(i.width=r.outerWidth(),i.height=r.outerHeight()),s=r.offset(),i.left=s.left,i.top=s.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(a=this.containers.length-1;a>=0;a--)s=this.containers[a].element.offset(),this.containers[a].containerCache.left=s.left,this.containers[a].containerCache.top=s.top,this.containers[a].containerCache.width=this.containers[a].element.outerWidth(),this.containers[a].containerCache.height=this.containers[a].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var a,i=t.options;i.placeholder&&i.placeholder.constructor!==String||(a=i.placeholder,i.placeholder={element:function(){var i=t.currentItem[0].nodeName.toLowerCase(),r=e("<"+i+">",t.document[0]).addClass(a||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===i?t.currentItem.children().each(function(){e("<td>&#160;</td>",t.document[0]).attr("colspan",e(this).attr("colspan")||1).appendTo(r)}):"img"===i&&r.attr("src",t.currentItem.attr("src")),a||r.css("visibility","hidden"),r},update:function(e,r){(!a||i.forcePlaceholderSize)&&(r.height()||r.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),r.width()||r.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10)))}}),t.placeholder=e(i.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),i.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var a,i,r,s,n,o,d,u,h,l,m=null,c=null;for(a=this.containers.length-1;a>=0;a--)if(!e.contains(this.currentItem[0],this.containers[a].element[0]))if(this._intersectsWith(this.containers[a].containerCache)){if(m&&e.contains(this.containers[a].element[0],m.element[0]))continue;m=this.containers[a],c=a}else this.containers[a].containerCache.over&&(this.containers[a]._trigger("out",t,this._uiHash(this)),this.containers[a].containerCache.over=0);if(m)if(1===this.containers.length)this.containers[c].containerCache.over||(this.containers[c]._trigger("over",t,this._uiHash(this)),this.containers[c].containerCache.over=1);else{for(r=1e4,s=null,h=m.floating||this._isFloating(this.currentItem),n=h?"left":"top",o=h?"width":"height",l=h?"clientX":"clientY",i=this.items.length-1;i>=0;i--)e.contains(this.containers[c].element[0],this.items[i].item[0])&&this.items[i].item[0]!==this.currentItem[0]&&(d=this.items[i].item.offset()[n],u=!1,t[l]-d>this.items[i][o]/2&&(u=!0),r>Math.abs(t[l]-d)&&(r=Math.abs(t[l]-d),s=this.items[i],this.direction=u?"up":"down"));if(!s&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[c])return;s?this._rearrange(t,s,null,!0):this._rearrange(t,null,this.containers[c].element,!0),this._trigger("change",t,this._uiHash()),this.containers[c]._trigger("change",t,this._uiHash(this)),this.currentContainer=this.containers[c],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[c]._trigger("over",t,this._uiHash(this)),this.containers[c].containerCache.over=1}},_createHelper:function(t){var a=this.options,i=e.isFunction(a.helper)?e(a.helper.apply(this.element[0],[t,this.currentItem])):"clone"===a.helper?this.currentItem.clone():this.currentItem;return i.parents("body").length||e("parent"!==a.appendTo?a.appendTo:this.currentItem[0].parentNode)[0].appendChild(i[0]),i[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!i[0].style.width||a.forceHelperSize)&&i.width(this.currentItem.width()),(!i[0].style.height||a.forceHelperSize)&&i.height(this.currentItem.height()),i},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,a,i,r=this.options;"parent"===r.containment&&(r.containment=this.helper[0].parentNode),("document"===r.containment||"window"===r.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e("document"===r.containment?document:window).width()-this.helperProportions.width-this.margins.left,(e("document"===r.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(r.containment)||(t=e(r.containment)[0],a=e(r.containment).offset(),i="hidden"!==e(t).css("overflow"),this.containment=[a.left+(parseInt(e(t).css("borderLeftWidth"),10)||0)+(parseInt(e(t).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(e(t).css("borderTopWidth"),10)||0)+(parseInt(e(t).css("paddingTop"),10)||0)-this.margins.top,a.left+(i?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css("borderLeftWidth"),10)||0)-(parseInt(e(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(i?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css("borderTopWidth"),10)||0)-(parseInt(e(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,a){a||(a=this.position);var i="absolute"===t?1:-1,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,s=/(html|body)/i.test(r[0].tagName);return{top:a.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():s?0:r.scrollTop())*i,left:a.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():s?0:r.scrollLeft())*i}},_generatePosition:function(t){var a,i,r=this.options,s=t.pageX,n=t.pageY,o="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,d=/(html|body)/i.test(o[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(s=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(n=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(n=this.containment[3]+this.offset.click.top)),r.grid&&(a=this.originalPageY+Math.round((n-this.originalPageY)/r.grid[1])*r.grid[1],n=this.containment?a-this.offset.click.top>=this.containment[1]&&a-this.offset.click.top<=this.containment[3]?a:a-this.offset.click.top>=this.containment[1]?a-r.grid[1]:a+r.grid[1]:a,i=this.originalPageX+Math.round((s-this.originalPageX)/r.grid[0])*r.grid[0],s=this.containment?i-this.offset.click.left>=this.containment[0]&&i-this.offset.click.left<=this.containment[2]?i:i-this.offset.click.left>=this.containment[0]?i-r.grid[0]:i+r.grid[0]:i)),{top:n-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():d?0:o.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():d?0:o.scrollLeft())}},_rearrange:function(e,t,a,i){a?a[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var r=this.counter;this._delay(function(){r===this.counter&&this.refreshPositions(!i)})},_clear:function(e,t){function a(e,t,a){return function(i){a._trigger(e,i,t._uiHash(t))}}this.reverting=!1;var i,r=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)("auto"===this._storedCSS[i]||"static"===this._storedCSS[i])&&(this._storedCSS[i]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!t&&r.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||t||r.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(t||(r.push(function(e){this._trigger("remove",e,this._uiHash())}),r.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),r.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;i>=0;i--)t||r.push(a("deactivate",this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(a("out",this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!t){for(this._trigger("beforeStop",e,this._uiHash()),i=0;r.length>i;i++)r[i].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!1}if(t||this._trigger("beforeStop",e,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!t){for(i=0;r.length>i;i++)r[i].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var a=t||this;return{helper:a.helper,placeholder:a.placeholder||e([]),position:a.position,originalPosition:a.originalPosition,offset:a.positionAbs,item:a.currentItem,sender:t?t.element:null}}}),e.widget("ui.accordion",{version:"1.11.0-beta.2",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").removeUniqueId(),this._destroyIcons(),e=this.headers.next().removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&(this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)),void 0)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var a=e.ui.keyCode,i=this.headers.length,r=this.headers.index(t.target),s=!1;switch(t.keyCode){case a.RIGHT:case a.DOWN:s=this.headers[(r+1)%i];break;case a.LEFT:case a.UP:s=this.headers[(r-1+i)%i];break;case a.SPACE:case a.ENTER:this._eventHandler(t);break;case a.HOME:s=this.headers[0];break;case a.END:s=this.headers[i-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var t,a=this.options,i=a.heightStyle,r=this.element.parent();this.active=this._findActive(a.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(){var t=e(this),a=t.uniqueId().attr("id"),i=t.next(),r=i.uniqueId().attr("id");
+t.attr("aria-controls",r),i.attr("aria-labelledby",a)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(a.event),"fill"===i?(t=r.height(),this.element.siblings(":visible").each(function(){var a=e(this),i=a.css("position");"absolute"!==i&&"fixed"!==i&&(t-=a.outerHeight(!0))}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===i&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var a=this._findActive(t)[0];a!==this.active[0]&&(a=a||this.active[0],this._eventHandler({target:a,currentTarget:a,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var a={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){a[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,a),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var a=this.options,i=this.active,r=e(t.currentTarget),s=r[0]===i[0],n=s&&a.collapsible,o=n?e():r.next(),d=i.next(),u={oldHeader:i,oldPanel:d,newHeader:n?e():r,newPanel:o};t.preventDefault(),s&&!a.collapsible||this._trigger("beforeActivate",t,u)===!1||(a.active=n?!1:this.headers.index(r),this.active=s?e():r,this._toggle(u),i.removeClass("ui-accordion-header-active ui-state-active"),a.icons&&i.children(".ui-accordion-header-icon").removeClass(a.icons.activeHeader).addClass(a.icons.header),s||(r.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),a.icons&&r.children(".ui-accordion-header-icon").removeClass(a.icons.header).addClass(a.icons.activeHeader),r.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var a=t.newPanel,i=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=a,this.prevHide=i,this.options.animate?this._animate(a,i,t):(i.hide(),a.show(),this._toggleComplete(t)),i.attr({"aria-hidden":"true"}),i.prev().attr("aria-selected","false"),a.length&&i.length?i.prev().attr({tabIndex:-1,"aria-expanded":"false"}):a.length&&this.headers.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),a.attr("aria-hidden","false").prev().attr({"aria-selected":"true",tabIndex:0,"aria-expanded":"true"})},_animate:function(e,t,a){var i,r,s,n=this,o=0,d=e.length&&(!t.length||e.index()<t.index()),u=this.options.animate||{},h=d&&u.down||u,l=function(){n._toggleComplete(a)};return"number"==typeof h&&(s=h),"string"==typeof h&&(r=h),r=r||h.easing||u.easing,s=s||h.duration||u.duration,t.length?e.length?(i=e.show().outerHeight(),t.animate(this.hideProps,{duration:s,easing:r,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(this.showProps,{duration:s,easing:r,complete:l,step:function(e,a){a.now=Math.round(e),"height"!==a.prop?o+=a.now:"content"!==n.options.heightStyle&&(a.now=Math.round(i-t.outerHeight()-o),o=0)}}),void 0):t.animate(this.hideProps,s,r,l):e.animate(this.showProps,s,r,l)},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}}),e.widget("ui.menu",{version:"1.11.0-beta.2",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},items:"> *",menus:"ul",position:{my:"left-1 top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item":function(e){e.preventDefault()},"click .ui-menu-item":function(t){var a=e(t.target);!this.mouseHandled&&a.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),a.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&e(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var a=e(t.currentTarget);a.siblings(".ui-state-active").removeClass("ui-state-active"),this.focus(t,a)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var a=this.active||this.element.find(this.options.items).eq(0);t||this.focus(e,a)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){this._closeOnDocumentClick(e)&&this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-menu-icons ui-front").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").removeUniqueId().removeClass("ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var i,r,s,n,o,d=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:d=!1,r=this.previousFilter||"",s=String.fromCharCode(t.keyCode),n=!1,clearTimeout(this.filterTimer),s===r?n=!0:s=r+s,o=RegExp("^"+a(s),"i"),i=this.activeMenu.find(this.options.items).filter(function(){return o.test(e(this).text())}),i=n&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(s=String.fromCharCode(t.keyCode),o=RegExp("^"+a(s),"i"),i=this.activeMenu.find(this.options.items).filter(function(){return o.test(e(this).text())})),i.length?(this.focus(t,i),i.length>1?(this.previousFilter=s,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}d&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.is("[aria-haspopup='true']")?this.expand(e):this.select(e))},refresh:function(){var t,a,i=this,r=this.options.icons.submenu,s=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),s.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-front").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),a=t.parent(),i=e("<span>").addClass("ui-menu-icon ui-icon "+r).data("ui-menu-submenu-carat",!0);a.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",a.attr("id"))}),t=s.add(this.element),a=t.find(this.options.items),a.not(".ui-menu-item").each(function(){var t=e(this);i._isDivider(t)&&t.addClass("ui-widget-content ui-menu-divider")}),a.not(".ui-menu-item, .ui-menu-divider").addClass("ui-menu-item").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),a.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){"icons"===e&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},focus:function(e,t){var a,i;this.blur(e,e&&"focus"===e.type),this._scrollIntoView(t),this.active=t.first(),i=this.active.addClass("ui-state-focus").removeClass("ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),this.active.parent().closest(".ui-menu-item").addClass("ui-state-active"),e&&"keydown"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),a=t.children(".ui-menu"),a.length&&e&&/^mouse/.test(e.type)&&this._startOpening(a),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var a,i,r,s,n,o;this._hasScroll()&&(a=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,i=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,r=t.offset().top-this.activeMenu.offset().top-a-i,s=this.activeMenu.scrollTop(),n=this.activeMenu.height(),o=t.outerHeight(),0>r?this.activeMenu.scrollTop(s+r):r+o>n&&this.activeMenu.scrollTop(s+r-n+o))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),"true"===e.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var a=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(a)},collapseAll:function(t,a){clearTimeout(this.timer),this.timer=this._delay(function(){var i=a?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));i.length||(i=this.element),this._close(i),this.blur(t),this.activeMenu=i},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find(".ui-state-active").not(".ui-state-focus").removeClass("ui-state-active")},_closeOnDocumentClick:function(t){return!e(t.target).closest(".ui-menu").length},_isDivider:function(e){return!/[^\-\u2014\u2013\s]/.test(e.text())},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,a){var i;this.active&&(i="first"===e||"last"===e?this.active["first"===e?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[e+"All"](".ui-menu-item").eq(0)),i&&i.length&&this.active||(i=this.activeMenu.find(this.options.items)[t]()),this.focus(a,i)},nextPage:function(t){var a,i,r;return this.active?(this.isLastItem()||(this._hasScroll()?(i=this.active.offset().top,r=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return a=e(this),0>a.offset().top-i-r}),this.focus(t,a)):this.focus(t,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(t),void 0)},previousPage:function(t){var a,i,r;return this.active?(this.isFirstItem()||(this._hasScroll()?(i=this.active.offset().top,r=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return a=e(this),a.offset().top-i+r>0}),this.focus(t,a)):this.focus(t,this.activeMenu.find(this.options.items).first())),void 0):(this.next(t),void 0)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var a={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,a)}}),e.widget("ui.autocomplete",{version:"1.11.0-beta.2",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,a,i,r=this.element[0].nodeName.toLowerCase(),s="textarea"===r,n="input"===r;this.isMultiLine=s?!0:n?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[s||n?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(r){if(this.element.prop("readOnly"))return t=!0,i=!0,a=!0,void 0;t=!1,i=!1,a=!1;var s=e.ui.keyCode;switch(r.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",r);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",r);break;case s.UP:t=!0,this._keyEvent("previous",r);break;case s.DOWN:t=!0,this._keyEvent("next",r);break;case s.ENTER:this.menu.active&&(t=!0,r.preventDefault(),this.menu.select(r));break;case s.TAB:this.menu.active&&this.menu.select(r);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(r),r.preventDefault());break;default:a=!0,this._searchTimeout(r)}},keypress:function(i){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&i.preventDefault(),void 0;if(!a){var r=e.ui.keyCode;switch(i.keyCode){case r.PAGE_UP:this._move("previousPage",i);break;case r.PAGE_DOWN:this._move("nextPage",i);break;case r.UP:this._keyEvent("previous",i);break;case r.DOWN:this._keyEvent("next",i)}}},input:function(e){return i?(i=!1,e.preventDefault(),void 0):(this._searchTimeout(e),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(e),this._change(e),void 0)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var a=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(i){i.target===t.element[0]||i.target===a||e.contains(a,i.target)||t.close()})})},menufocus:function(t,a){var i,r;return this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),void 0):(r=a.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:r})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(r.value),i=a.item.attr("aria-label")||r.value,i&&jQuery.trim(i).length&&(this.liveRegion.children().hide(),e("<div>").text(i).appendTo(this.liveRegion)),void 0)},menuselect:function(e,t){var a=t.item.data("ui-autocomplete-item"),i=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=i,this._delay(function(){this.previous=i,this.selectedItem=a})),!1!==this._trigger("select",e,{item:a})&&this._value(a.value),this.term=this._value(),this.close(e),this.selectedItem=a}}),this.liveRegion=e("<span>",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,a,i=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(a,i){i(e.ui.autocomplete.filter(t,a.term))}):"string"==typeof this.options.source?(a=this.options.source,this.source=function(t,r){i.xhr&&i.xhr.abort(),i.xhr=e.ajax({url:a,data:t,dataType:"json",success:function(e){r(e)},error:function(){r([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),a=this.menu.element.is(":visible"),i=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;(!t||t&&!a&&!i)&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length<this.options.minLength?this.close(t):this._trigger("search",t)!==!1?this._search(e):void 0},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var t=++this.requestIndex;return e.proxy(function(e){t===this.requestIndex&&this.__response(e),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},this)},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return"string"==typeof t?{label:t,value:t}:e.extend({},t,{label:t.label||t.value,value:t.value||t.label})})},_suggest:function(t){var a=this.menu.element.empty();this._renderMenu(a,t),this.isNewMenu=!0,this.menu.refresh(),a.show(),this._resizeMenu(),a.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,a){var i=this;e.each(a,function(e,a){i._renderItemData(t,a)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,a){return e("<li>").text(a.label).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[e](t),void 0):(this.search(null,t),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,a){var i=RegExp(e.ui.autocomplete.escapeRegex(a),"i");return e.grep(t,function(e){return i.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var a;this._superApply(arguments),this.options.disabled||this.cancelSearch||(a=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.children().hide(),e("<div>").text(a).appendTo(this.liveRegion))}}),e.ui.autocomplete;var l,m="ui-button ui-widget ui-state-default ui-corner-all",c="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",p=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},f=function(t){var a=t.name,i=t.form,r=e([]);return a&&(a=a.replace(/'/g,"\\'"),r=i?e(i).find("[name='"+a+"'][type=radio]"):e("[name='"+a+"'][type=radio]",t.ownerDocument).filter(function(){return!this.form})),r};e.widget("ui.button",{version:"1.11.0-beta.2",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,p),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,a=this.options,i="checkbox"===this.type||"radio"===this.type,r=i?"":"ui-state-active";null===a.label&&(a.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(m).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){a.disabled||this===l&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){a.disabled||e(this).removeClass(r)}).bind("click"+this.eventNamespace,function(e){a.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this._on({focus:function(){this.buttonElement.addClass("ui-state-focus")},blur:function(){this.buttonElement.removeClass("ui-state-focus")}}),i&&this.element.bind("change"+this.eventNamespace,function(){t.refresh()}),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return a.disabled?!1:void 0}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(a.disabled)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var i=t.element[0];f(i).not(i).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return a.disabled?!1:(e(this).addClass("ui-state-active"),l=this,t.document.one("mouseup",function(){l=null}),void 0)}).bind("mouseup"+this.eventNamespace,function(){return a.disabled?!1:(e(this).removeClass("ui-state-active"),void 0)}).bind("keydown"+this.eventNamespace,function(t){return a.disabled?!1:((t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active"),void 0)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",a.disabled),this._resetButton()},_determineButtonType:function(){var e,t,a;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),a=this.element.is(":checked"),a&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",a)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(m+" ui-state-active "+c).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){return this._super(e,t),"disabled"===e?(this.widget().toggleClass("ui-state-disabled",!!t),this.element.prop("disabled",!!t),t&&("checkbox"===this.type||"radio"===this.type?this.buttonElement.removeClass("ui-state-focus"):this.buttonElement.removeClass("ui-state-focus ui-state-active")),void 0):(this._resetButton(),void 0)},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),"radio"===this.type?f(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),void 0;var t=this.buttonElement.removeClass(c),a=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),i=this.options.icons,r=i.primary&&i.secondary,s=[];i.primary||i.secondary?(this.options.text&&s.push("ui-button-text-icon"+(r?"s":i.primary?"-primary":"-secondary")),i.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+i.primary+"'></span>"),i.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+i.secondary+"'></span>"),this.options.text||(s.push(r?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(a)))):s.push("ui-button-text-only"),t.addClass(s.join(" "))}}),e.widget("ui.buttonset",{version:"1.11.0-beta.2",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){"disabled"===e&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t="rtl"===this.element.css("direction"),a=this.element.find(this.options.items),i=a.filter(":ui-button");a.not(":ui-button").button(),i.button("refresh"),this.buttons=a.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}}),e.ui.button,e.extend(e.ui,{datepicker:{version:"1.11.0-beta.2"}});var g;e.extend(r.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return n(this._defaults,e||{}),this},_attachDatepicker:function(t,a){var i,r,s;i=t.nodeName.toLowerCase(),r="div"===i||"span"===i,t.id||(this.uuid+=1,t.id="dp"+this.uuid),s=this._newInst(e(t),r),s.settings=e.extend({},a||{}),"input"===i?this._connectDatepicker(t,s):r&&this._inlineDatepicker(t,s)},_newInst:function(t,a){var i=t[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:i,input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:a,dpDiv:a?s(e("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(t,a){var i=e(t);a.append=e([]),a.trigger=e([]),i.hasClass(this.markerClassName)||(this._attachments(i,a),i.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(a),e.data(t,"datepicker",a),a.settings.disabled&&this._disableDatepicker(t))},_attachments:function(t,a){var i,r,s,n=this._get(a,"appendText"),o=this._get(a,"isRTL");a.append&&a.append.remove(),n&&(a.append=e("<span class='"+this._appendClass+"'>"+n+"</span>"),t[o?"before":"after"](a.append)),t.unbind("focus",this._showDatepicker),a.trigger&&a.trigger.remove(),i=this._get(a,"showOn"),("focus"===i||"both"===i)&&t.focus(this._showDatepicker),("button"===i||"both"===i)&&(r=this._get(a,"buttonText"),s=this._get(a,"buttonImage"),a.trigger=e(this._get(a,"buttonImageOnly")?e("<img/>").addClass(this._triggerClass).attr({src:s,alt:r,title:r}):e("<button type='button'></button>").addClass(this._triggerClass).html(s?e("<img/>").attr({src:s,alt:r,title:r}):r)),t[o?"before":"after"](a.trigger),a.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,a,i,r,s=new Date(2009,11,20),n=this._get(e,"dateFormat");n.match(/[DM]/)&&(t=function(e){for(a=0,i=0,r=0;e.length>r;r++)e[r].length>a&&(a=e[r].length,i=r);return i},s.setMonth(t(this._get(e,n.match(/MM/)?"monthNames":"monthNamesShort"))),s.setDate(t(this._get(e,n.match(/DD/)?"dayNames":"dayNamesShort"))+20-s.getDay())),e.input.attr("size",this._formatDate(e,s).length)}},_inlineDatepicker:function(t,a){var i=e(t);i.hasClass(this.markerClassName)||(i.addClass(this.markerClassName).append(a.dpDiv),e.data(t,"datepicker",a),this._setDate(a,this._getDefaultDate(a),!0),this._updateDatepicker(a),this._updateAlternate(a),a.settings.disabled&&this._disableDatepicker(t),a.dpDiv.css("display","block"))},_dialogDatepicker:function(t,a,i,r,s){var o,d,u,h,l,m=this._dialogInst;return m||(this.uuid+=1,o="dp"+this.uuid,this._dialogInput=e("<input type='text' id='"+o+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),m=this._dialogInst=this._newInst(this._dialogInput,!1),m.settings={},e.data(this._dialogInput[0],"datepicker",m)),n(m.settings,r||{}),a=a&&a.constructor===Date?this._formatDate(m,a):a,this._dialogInput.val(a),this._pos=s?s.length?s:[s.pageX,s.pageY]:null,this._pos||(d=document.documentElement.clientWidth,u=document.documentElement.clientHeight,h=document.documentElement.scrollLeft||document.body.scrollLeft,l=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[d/2-100+h,u/2-150+l]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),m.settings.onSelect=i,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],"datepicker",m),this},_destroyDatepicker:function(t){var a,i=e(t),r=e.data(t,"datepicker");i.hasClass(this.markerClassName)&&(a=t.nodeName.toLowerCase(),e.removeData(t,"datepicker"),"input"===a?(r.append.remove(),r.trigger.remove(),i.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===a||"span"===a)&&i.removeClass(this.markerClassName).empty())
+},_enableDatepicker:function(t){var a,i,r=e(t),s=e.data(t,"datepicker");r.hasClass(this.markerClassName)&&(a=t.nodeName.toLowerCase(),"input"===a?(t.disabled=!1,s.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===a||"span"===a)&&(i=r.children("."+this._inlineClass),i.children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var a,i,r=e(t),s=e.data(t,"datepicker");r.hasClass(this.markerClassName)&&(a=t.nodeName.toLowerCase(),"input"===a?(t.disabled=!0,s.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===a||"span"===a)&&(i=r.children("."+this._inlineClass),i.children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,"datepicker")}catch(a){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(t,a,i){var r,s,o,d,u=this._getInst(t);return 2===arguments.length&&"string"==typeof a?"defaults"===a?e.extend({},e.datepicker._defaults):u?"all"===a?e.extend({},u.settings):this._get(u,a):null:(r=a||{},"string"==typeof a&&(r={},r[a]=i),u&&(this._curInst===u&&this._hideDatepicker(),s=this._getDateDatepicker(t,!0),o=this._getMinMaxDate(u,"min"),d=this._getMinMaxDate(u,"max"),n(u.settings,r),null!==o&&void 0!==r.dateFormat&&void 0===r.minDate&&(u.settings.minDate=this._formatDate(u,o)),null!==d&&void 0!==r.dateFormat&&void 0===r.maxDate&&(u.settings.maxDate=this._formatDate(u,d)),"disabled"in r&&(r.disabled?this._disableDatepicker(t):this._enableDatepicker(t)),this._attachments(e(t),u),this._autoSize(u),this._setDate(u,s),this._updateAlternate(u),this._updateDatepicker(u)),void 0)},_changeDatepicker:function(e,t,a){this._optionDatepicker(e,t,a)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var a=this._getInst(e);a&&(this._setDate(a,t),this._updateDatepicker(a),this._updateAlternate(a))},_getDateDatepicker:function(e,t){var a=this._getInst(e);return a&&!a.inline&&this._setDateFromField(a,t),a?this._getDate(a):null},_doKeyDown:function(t){var a,i,r,s=e.datepicker._getInst(t.target),n=!0,o=s.dpDiv.is(".ui-datepicker-rtl");if(s._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),n=!1;break;case 13:return r=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",s.dpDiv),r[0]&&e.datepicker._selectDay(t.target,s.selectedMonth,s.selectedYear,r[0]),a=e.datepicker._get(s,"onSelect"),a?(i=e.datepicker._formatDate(s),a.apply(s.input?s.input[0]:null,[i,s])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(s,"stepBigMonths"):-e.datepicker._get(s,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(s,"stepBigMonths"):+e.datepicker._get(s,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),n=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),n=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,o?1:-1,"D"),n=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(s,"stepBigMonths"):-e.datepicker._get(s,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),n=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,o?-1:1,"D"),n=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(s,"stepBigMonths"):+e.datepicker._get(s,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),n=t.ctrlKey||t.metaKey;break;default:n=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):n=!1;n&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var a,i,r=e.datepicker._getInst(t.target);return e.datepicker._get(r,"constrainInput")?(a=e.datepicker._possibleChars(e.datepicker._get(r,"dateFormat")),i=String.fromCharCode(null==t.charCode?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||" ">i||!a||a.indexOf(i)>-1):void 0},_doKeyUp:function(t){var a,i=e.datepicker._getInst(t.target);if(i.input.val()!==i.lastVal)try{a=e.datepicker.parseDate(e.datepicker._get(i,"dateFormat"),i.input?i.input.val():null,e.datepicker._getFormatConfig(i)),a&&(e.datepicker._setDateFromField(i),e.datepicker._updateAlternate(i),e.datepicker._updateDatepicker(i))}catch(r){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var a,r,s,o,d,u,h;a=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==a&&(e.datepicker._curInst.dpDiv.stop(!0,!0),a&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),r=e.datepicker._get(a,"beforeShow"),s=r?r.apply(t,[t,a]):{},s!==!1&&(n(a.settings,s),a.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(a),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),o=!1,e(t).parents().each(function(){return o|="fixed"===e(this).css("position"),!o}),d={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,a.dpDiv.empty(),a.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(a),d=e.datepicker._checkOffset(a,d,o),a.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":o?"fixed":"absolute",display:"none",left:d.left+"px",top:d.top+"px"}),a.inline||(u=e.datepicker._get(a,"showAnim"),h=e.datepicker._get(a,"duration"),a.dpDiv.css("z-index",i(e(t))+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[u]?a.dpDiv.show(u,e.datepicker._get(a,"showOptions"),h):a.dpDiv[u||"show"](u?h:null),e.datepicker._shouldFocusInput(a)&&a.input.focus(),e.datepicker._curInst=a))}},_updateDatepicker:function(t){this.maxRows=4,g=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t),t.dpDiv.find("."+this._dayOverClass+" a");var a,i=this._getNumberOfMonths(t),r=i[1],s=17;t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),r>1&&t.dpDiv.addClass("ui-datepicker-multi-"+r).css("width",s*r+"em"),t.dpDiv[(1!==i[0]||1!==i[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(a=t.yearshtml,setTimeout(function(){a===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),a=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&!e.input.is(":focus")},_checkOffset:function(t,a,i){var r=t.dpDiv.outerWidth(),s=t.dpDiv.outerHeight(),n=t.input?t.input.outerWidth():0,o=t.input?t.input.outerHeight():0,d=document.documentElement.clientWidth+(i?0:e(document).scrollLeft()),u=document.documentElement.clientHeight+(i?0:e(document).scrollTop());return a.left-=this._get(t,"isRTL")?r-n:0,a.left-=i&&a.left===t.input.offset().left?e(document).scrollLeft():0,a.top-=i&&a.top===t.input.offset().top+o?e(document).scrollTop():0,a.left-=Math.min(a.left,a.left+r>d&&d>r?Math.abs(a.left+r-d):0),a.top-=Math.min(a.top,a.top+s>u&&u>s?Math.abs(s+o):0),a},_findPos:function(t){for(var a,i=this._getInst(t),r=this._get(i,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[r?"previousSibling":"nextSibling"];return a=e(t).offset(),[a.left,a.top]},_hideDatepicker:function(t){var a,i,r,s,n=this._curInst;!n||t&&n!==e.data(t,"datepicker")||this._datepickerShowing&&(a=this._get(n,"showAnim"),i=this._get(n,"duration"),r=function(){e.datepicker._tidyDialog(n)},e.effects&&(e.effects.effect[a]||e.effects[a])?n.dpDiv.hide(a,e.datepicker._get(n,"showOptions"),i,r):n.dpDiv["slideDown"===a?"slideUp":"fadeIn"===a?"fadeOut":"hide"](a?i:null,r),a||r(),this._datepickerShowing=!1,s=this._get(n,"onClose"),s&&s.apply(n.input?n.input[0]:null,[n.input?n.input.val():"",n]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(e.datepicker._curInst){var a=e(t.target),i=e.datepicker._getInst(a[0]);(a[0].id!==e.datepicker._mainDivId&&0===a.parents("#"+e.datepicker._mainDivId).length&&!a.hasClass(e.datepicker.markerClassName)&&!a.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||a.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==i)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,a,i){var r=e(t),s=this._getInst(r[0]);this._isDisabledDatepicker(r[0])||(this._adjustInstDate(s,a+("M"===i?this._get(s,"showCurrentAtPos"):0),i),this._updateDatepicker(s))},_gotoToday:function(t){var a,i=e(t),r=this._getInst(i[0]);this._get(r,"gotoCurrent")&&r.currentDay?(r.selectedDay=r.currentDay,r.drawMonth=r.selectedMonth=r.currentMonth,r.drawYear=r.selectedYear=r.currentYear):(a=new Date,r.selectedDay=a.getDate(),r.drawMonth=r.selectedMonth=a.getMonth(),r.drawYear=r.selectedYear=a.getFullYear()),this._notifyChange(r),this._adjustDate(i)},_selectMonthYear:function(t,a,i){var r=e(t),s=this._getInst(r[0]);s["selected"+("M"===i?"Month":"Year")]=s["draw"+("M"===i?"Month":"Year")]=parseInt(a.options[a.selectedIndex].value,10),this._notifyChange(s),this._adjustDate(r)},_selectDay:function(t,a,i,r){var s,n=e(t);e(r).hasClass(this._unselectableClass)||this._isDisabledDatepicker(n[0])||(s=this._getInst(n[0]),s.selectedDay=s.currentDay=e("a",r).html(),s.selectedMonth=s.currentMonth=a,s.selectedYear=s.currentYear=i,this._selectDate(t,this._formatDate(s,s.currentDay,s.currentMonth,s.currentYear)))},_clearDate:function(t){var a=e(t);this._selectDate(a,"")},_selectDate:function(t,a){var i,r=e(t),s=this._getInst(r[0]);a=null!=a?a:this._formatDate(s),s.input&&s.input.val(a),this._updateAlternate(s),i=this._get(s,"onSelect"),i?i.apply(s.input?s.input[0]:null,[a,s]):s.input&&s.input.trigger("change"),s.inline?this._updateDatepicker(s):(this._hideDatepicker(),this._lastInput=s.input[0],"object"!=typeof s.input[0]&&s.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var a,i,r,s=this._get(t,"altField");s&&(a=this._get(t,"altFormat")||this._get(t,"dateFormat"),i=this._getDate(t),r=this.formatDate(a,i,this._getFormatConfig(t)),e(s).each(function(){e(this).val(r)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,""]},iso8601Week:function(e){var t,a=new Date(e.getTime());return a.setDate(a.getDate()+4-(a.getDay()||7)),t=a.getTime(),a.setMonth(0),a.setDate(1),Math.floor(Math.round((t-a)/864e5)/7)+1},parseDate:function(t,a,i){if(null==t||null==a)throw"Invalid arguments";if(a="object"==typeof a?""+a:a+"",""===a)return null;var r,s,n,o,d=0,u=(i?i.shortYearCutoff:null)||this._defaults.shortYearCutoff,h="string"!=typeof u?u:(new Date).getFullYear()%100+parseInt(u,10),l=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,m=(i?i.dayNames:null)||this._defaults.dayNames,c=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,p=(i?i.monthNames:null)||this._defaults.monthNames,f=-1,g=-1,y=-1,x=-1,v=!1,T=function(e){var a=t.length>r+1&&t.charAt(r+1)===e;return a&&r++,a},k=function(e){var t=T(e),i="@"===e?14:"!"===e?20:"y"===e&&t?4:"o"===e?3:2,r=RegExp("^\\d{1,"+i+"}"),s=a.substring(d).match(r);if(!s)throw"Missing number at position "+d;return d+=s[0].length,parseInt(s[0],10)},S=function(t,i,r){var s=-1,n=e.map(T(t)?r:i,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(n,function(e,t){var i=t[1];return a.substr(d,i.length).toLowerCase()===i.toLowerCase()?(s=t[0],d+=i.length,!1):void 0}),-1!==s)return s+1;throw"Unknown name at position "+d},b=function(){if(a.charAt(d)!==t.charAt(r))throw"Unexpected literal at position "+d;d++};for(r=0;t.length>r;r++)if(v)"'"!==t.charAt(r)||T("'")?b():v=!1;else switch(t.charAt(r)){case"d":y=k("d");break;case"D":S("D",l,m);break;case"o":x=k("o");break;case"m":g=k("m");break;case"M":g=S("M",c,p);break;case"y":f=k("y");break;case"@":o=new Date(k("@")),f=o.getFullYear(),g=o.getMonth()+1,y=o.getDate();break;case"!":o=new Date((k("!")-this._ticksTo1970)/1e4),f=o.getFullYear(),g=o.getMonth()+1,y=o.getDate();break;case"'":T("'")?b():v=!0;break;default:b()}if(a.length>d&&(n=a.substr(d),!/^\s+/.test(n)))throw"Extra/unparsed characters found in date: "+n;if(-1===f?f=(new Date).getFullYear():100>f&&(f+=(new Date).getFullYear()-(new Date).getFullYear()%100+(h>=f?0:-100)),x>-1)for(g=1,y=x;;){if(s=this._getDaysInMonth(f,g-1),s>=y)break;g++,y-=s}if(o=this._daylightSavingAdjust(new Date(f,g-1,y)),o.getFullYear()!==f||o.getMonth()+1!==g||o.getDate()!==y)throw"Invalid date";return o},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,a){if(!t)return"";var i,r=(a?a.dayNamesShort:null)||this._defaults.dayNamesShort,s=(a?a.dayNames:null)||this._defaults.dayNames,n=(a?a.monthNamesShort:null)||this._defaults.monthNamesShort,o=(a?a.monthNames:null)||this._defaults.monthNames,d=function(t){var a=e.length>i+1&&e.charAt(i+1)===t;return a&&i++,a},u=function(e,t,a){var i=""+t;if(d(e))for(;a>i.length;)i="0"+i;return i},h=function(e,t,a,i){return d(e)?i[t]:a[t]},l="",m=!1;if(t)for(i=0;e.length>i;i++)if(m)"'"!==e.charAt(i)||d("'")?l+=e.charAt(i):m=!1;else switch(e.charAt(i)){case"d":l+=u("d",t.getDate(),2);break;case"D":l+=h("D",t.getDay(),r,s);break;case"o":l+=u("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":l+=u("m",t.getMonth()+1,2);break;case"M":l+=h("M",t.getMonth(),n,o);break;case"y":l+=d("y")?t.getFullYear():(10>t.getYear()%100?"0":"")+t.getYear()%100;break;case"@":l+=t.getTime();break;case"!":l+=1e4*t.getTime()+this._ticksTo1970;break;case"'":d("'")?l+="'":m=!0;break;default:l+=e.charAt(i)}return l},_possibleChars:function(e){var t,a="",i=!1,r=function(a){var i=e.length>t+1&&e.charAt(t+1)===a;return i&&t++,i};for(t=0;e.length>t;t++)if(i)"'"!==e.charAt(t)||r("'")?a+=e.charAt(t):i=!1;else switch(e.charAt(t)){case"d":case"m":case"y":case"@":a+="0123456789";break;case"D":case"M":return null;case"'":r("'")?a+="'":i=!0;break;default:a+=e.charAt(t)}return a},_get:function(e,t){return void 0!==e.settings[t]?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var a=this._get(e,"dateFormat"),i=e.lastVal=e.input?e.input.val():null,r=this._getDefaultDate(e),s=r,n=this._getFormatConfig(e);try{s=this.parseDate(a,i,n)||r}catch(o){i=t?"":i}e.selectedDay=s.getDate(),e.drawMonth=e.selectedMonth=s.getMonth(),e.drawYear=e.selectedYear=s.getFullYear(),e.currentDay=i?s.getDate():0,e.currentMonth=i?s.getMonth():0,e.currentYear=i?s.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,a,i){var r=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},s=function(a){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),a,e.datepicker._getFormatConfig(t))}catch(i){}for(var r=(a.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,s=r.getFullYear(),n=r.getMonth(),o=r.getDate(),d=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,u=d.exec(a);u;){switch(u[2]||"d"){case"d":case"D":o+=parseInt(u[1],10);break;case"w":case"W":o+=7*parseInt(u[1],10);break;case"m":case"M":n+=parseInt(u[1],10),o=Math.min(o,e.datepicker._getDaysInMonth(s,n));break;case"y":case"Y":s+=parseInt(u[1],10),o=Math.min(o,e.datepicker._getDaysInMonth(s,n))}u=d.exec(a)}return new Date(s,n,o)},n=null==a||""===a?i:"string"==typeof a?s(a):"number"==typeof a?isNaN(a)?i:r(a):new Date(a.getTime());return n=n&&"Invalid Date"==""+n?i:n,n&&(n.setHours(0),n.setMinutes(0),n.setSeconds(0),n.setMilliseconds(0)),this._daylightSavingAdjust(n)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,a){var i=!t,r=e.selectedMonth,s=e.selectedYear,n=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=n.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=n.getMonth(),e.drawYear=e.selectedYear=e.currentYear=n.getFullYear(),r===e.selectedMonth&&s===e.selectedYear||a||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(i?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&""===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var a=this._get(t,"stepMonths"),i="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){e.datepicker._adjustDate(i,-a,"M")},next:function(){e.datepicker._adjustDate(i,+a,"M")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(i)},selectDay:function(){return e.datepicker._selectDay(i,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(i,this,"M"),!1},selectYear:function(){return e.datepicker._selectMonthYear(i,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,a,i,r,s,n,o,d,u,h,l,m,c,p,f,g,y,x,v,T,k,S,b,N,M,D,w,_,A,j,F,C,L,H,J,P,z,R,E,O=new Date,Y=this._daylightSavingAdjust(new Date(O.getFullYear(),O.getMonth(),O.getDate())),I=this._get(e,"isRTL"),Q=this._get(e,"showButtonPanel"),W=this._get(e,"hideIfNoPrevNext"),B=this._get(e,"navigationAsDateFormat"),V=this._getNumberOfMonths(e),K=this._get(e,"showCurrentAtPos"),G=this._get(e,"stepMonths"),U=1!==V[0]||1!==V[1],q=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),Z=this._getMinMaxDate(e,"min"),X=this._getMinMaxDate(e,"max"),$=e.drawMonth-K,et=e.drawYear;if(0>$&&($+=12,et--),X)for(t=this._daylightSavingAdjust(new Date(X.getFullYear(),X.getMonth()-V[0]*V[1]+1,X.getDate())),t=Z&&Z>t?Z:t;this._daylightSavingAdjust(new Date(et,$,1))>t;)$--,0>$&&($=11,et--);for(e.drawMonth=$,e.drawYear=et,a=this._get(e,"prevText"),a=B?this.formatDate(a,this._daylightSavingAdjust(new Date(et,$-G,1)),this._getFormatConfig(e)):a,i=this._canAdjustMonth(e,-1,et,$)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+a+"'><span class='ui-icon ui-icon-circle-triangle-"+(I?"e":"w")+"'>"+a+"</span></a>":W?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+a+"'><span class='ui-icon ui-icon-circle-triangle-"+(I?"e":"w")+"'>"+a+"</span></a>",r=this._get(e,"nextText"),r=B?this.formatDate(r,this._daylightSavingAdjust(new Date(et,$+G,1)),this._getFormatConfig(e)):r,s=this._canAdjustMonth(e,1,et,$)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+r+"'><span class='ui-icon ui-icon-circle-triangle-"+(I?"w":"e")+"'>"+r+"</span></a>":W?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+r+"'><span class='ui-icon ui-icon-circle-triangle-"+(I?"w":"e")+"'>"+r+"</span></a>",n=this._get(e,"currentText"),o=this._get(e,"gotoCurrent")&&e.currentDay?q:Y,n=B?this.formatDate(n,o,this._getFormatConfig(e)):n,d=e.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(e,"closeText")+"</button>",u=Q?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(I?d:"")+(this._isInRange(e,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+n+"</button>":"")+(I?"":d)+"</div>":"",h=parseInt(this._get(e,"firstDay"),10),h=isNaN(h)?0:h,l=this._get(e,"showWeek"),m=this._get(e,"dayNames"),c=this._get(e,"dayNamesMin"),p=this._get(e,"monthNames"),f=this._get(e,"monthNamesShort"),g=this._get(e,"beforeShowDay"),y=this._get(e,"showOtherMonths"),x=this._get(e,"selectOtherMonths"),v=this._getDefaultDate(e),T="",S=0;V[0]>S;S++){for(b="",this.maxRows=4,N=0;V[1]>N;N++){if(M=this._daylightSavingAdjust(new Date(et,$,e.selectedDay)),D=" ui-corner-all",w="",U){if(w+="<div class='ui-datepicker-group",V[1]>1)switch(N){case 0:w+=" ui-datepicker-group-first",D=" ui-corner-"+(I?"right":"left");break;case V[1]-1:w+=" ui-datepicker-group-last",D=" ui-corner-"+(I?"left":"right");break;default:w+=" ui-datepicker-group-middle",D=""}w+="'>"}for(w+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+D+"'>"+(/all|left/.test(D)&&0===S?I?s:i:"")+(/all|right/.test(D)&&0===S?I?i:s:"")+this._generateMonthYearHeader(e,$,et,Z,X,S>0||N>0,p,f)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",_=l?"<th class='ui-datepicker-week-col'>"+this._get(e,"weekHeader")+"</th>":"",k=0;7>k;k++)A=(k+h)%7,_+="<th scope='col'"+((k+h+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+m[A]+"'>"+c[A]+"</span></th>";for(w+=_+"</tr></thead><tbody>",j=this._getDaysInMonth(et,$),et===e.selectedYear&&$===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,j)),F=(this._getFirstDayOfMonth(et,$)-h+7)%7,C=Math.ceil((F+j)/7),L=U?this.maxRows>C?this.maxRows:C:C,this.maxRows=L,H=this._daylightSavingAdjust(new Date(et,$,1-F)),J=0;L>J;J++){for(w+="<tr>",P=l?"<td class='ui-datepicker-week-col'>"+this._get(e,"calculateWeek")(H)+"</td>":"",k=0;7>k;k++)z=g?g.apply(e.input?e.input[0]:null,[H]):[!0,""],R=H.getMonth()!==$,E=R&&!x||!z[0]||Z&&Z>H||X&&H>X,P+="<td class='"+((k+h+6)%7>=5?" ui-datepicker-week-end":"")+(R?" ui-datepicker-other-month":"")+(H.getTime()===M.getTime()&&$===e.selectedMonth&&e._keyEvent||v.getTime()===H.getTime()&&v.getTime()===M.getTime()?" "+this._dayOverClass:"")+(E?" "+this._unselectableClass+" ui-state-disabled":"")+(R&&!y?"":" "+z[1]+(H.getTime()===q.getTime()?" "+this._currentClass:"")+(H.getTime()===Y.getTime()?" ui-datepicker-today":""))+"'"+(R&&!y||!z[2]?"":" title='"+z[2].replace(/'/g,"&#39;")+"'")+(E?"":" data-handler='selectDay' data-event='click' data-month='"+H.getMonth()+"' data-year='"+H.getFullYear()+"'")+">"+(R&&!y?"&#xa0;":E?"<span class='ui-state-default'>"+H.getDate()+"</span>":"<a class='ui-state-default"+(H.getTime()===Y.getTime()?" ui-state-highlight":"")+(H.getTime()===q.getTime()?" ui-state-active":"")+(R?" ui-priority-secondary":"")+"' href='#'>"+H.getDate()+"</a>")+"</td>",H.setDate(H.getDate()+1),H=this._daylightSavingAdjust(H);w+=P+"</tr>"}$++,$>11&&($=0,et++),w+="</tbody></table>"+(U?"</div>"+(V[0]>0&&N===V[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),b+=w}T+=b}return T+=u,e._keyEvent=!1,T},_generateMonthYearHeader:function(e,t,a,i,r,s,n,o){var d,u,h,l,m,c,p,f,g=this._get(e,"changeMonth"),y=this._get(e,"changeYear"),x=this._get(e,"showMonthAfterYear"),v="<div class='ui-datepicker-title'>",T="";if(s||!g)T+="<span class='ui-datepicker-month'>"+n[t]+"</span>";else{for(d=i&&i.getFullYear()===a,u=r&&r.getFullYear()===a,T+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",h=0;12>h;h++)(!d||h>=i.getMonth())&&(!u||r.getMonth()>=h)&&(T+="<option value='"+h+"'"+(h===t?" selected='selected'":"")+">"+o[h]+"</option>");T+="</select>"}if(x||(v+=T+(!s&&g&&y?"":"&#xa0;")),!e.yearshtml)if(e.yearshtml="",s||!y)v+="<span class='ui-datepicker-year'>"+a+"</span>";else{for(l=this._get(e,"yearRange").split(":"),m=(new Date).getFullYear(),c=function(e){var t=e.match(/c[+\-].*/)?a+parseInt(e.substring(1),10):e.match(/[+\-].*/)?m+parseInt(e,10):parseInt(e,10);return isNaN(t)?m:t},p=c(l[0]),f=Math.max(p,c(l[1]||"")),p=i?Math.max(p,i.getFullYear()):p,f=r?Math.min(f,r.getFullYear()):f,e.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";f>=p;p++)e.yearshtml+="<option value='"+p+"'"+(p===a?" selected='selected'":"")+">"+p+"</option>";e.yearshtml+="</select>",v+=e.yearshtml,e.yearshtml=null}return v+=this._get(e,"yearSuffix"),x&&(v+=(!s&&g&&y?"":"&#xa0;")+T),v+="</div>"},_adjustInstDate:function(e,t,a){var i=e.drawYear+("Y"===a?t:0),r=e.drawMonth+("M"===a?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(i,r))+("D"===a?t:0),n=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(i,r,s)));e.selectedDay=n.getDate(),e.drawMonth=e.selectedMonth=n.getMonth(),e.drawYear=e.selectedYear=n.getFullYear(),("M"===a||"Y"===a)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var a=this._getMinMaxDate(e,"min"),i=this._getMinMaxDate(e,"max"),r=a&&a>t?a:t;return i&&r>i?i:r},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,a,i){var r=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(a,i+(0>t?t:r[0]*r[1]),1));return 0>t&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var a,i,r=this._getMinMaxDate(e,"min"),s=this._getMinMaxDate(e,"max"),n=null,o=null,d=this._get(e,"yearRange");return d&&(a=d.split(":"),i=(new Date).getFullYear(),n=parseInt(a[0],10),o=parseInt(a[1],10),a[0].match(/[+\-].*/)&&(n+=i),a[1].match(/[+\-].*/)&&(o+=i)),(!r||t.getTime()>=r.getTime())&&(!s||t.getTime()<=s.getTime())&&(!n||t.getFullYear()>=n)&&(!o||o>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t="string"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,a,i){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var r=t?"object"==typeof t?t:this._daylightSavingAdjust(new Date(i,a,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),r,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e("#"+e.datepicker._mainDivId).length&&e("body").append(e.datepicker.dpDiv);var a=Array.prototype.slice.call(arguments,1);return"string"!=typeof t||"isDisabled"!==t&&"getDate"!==t&&"widget"!==t?"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(a)):this.each(function(){"string"==typeof t?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(a)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(a))},e.datepicker=new r,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.11.0-beta.2",e.datepicker,e.widget("ui.dialog",{version:"1.11.0-beta.2",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"Close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var a=e(this).css(t).offset().top;0>a&&e(this).css("top",t.top-a)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var a,i=this;if(this._isOpen&&this._trigger("beforeClose",t)!==!1){if(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),!this.opener.filter(":focusable").focus().length)try{a=this.document[0].activeElement,a&&"body"!==a.nodeName.toLowerCase()&&e(a).blur()}catch(r){}this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,a){var i=!1,r=this.uiDialog.siblings(".ui-front:visible").map(function(){return+e(this).css("z-index")}).get(),s=Math.max.apply(null,r);return s>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",s+1),i=!0),i&&!a&&this._trigger("focus",t),i},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._trigger("open"),void 0)},_focusTabbable:function(){var e=this._focusedElement;e||(e=this.element.find("[autofocus]")),e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()
+},_keepFocus:function(t){function a(){var t=this.document[0].activeElement,a=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);a||this._focusTabbable()}t.preventDefault(),a.call(this),this._delay(a)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),void 0;if(t.keyCode===e.ui.keyCode.TAB){var a=this.uiDialog.find(":tabbable"),i=a.filter(":first"),r=a.filter(":last");t.target!==r[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==i[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){i.focus()}),t.preventDefault()):(this._delay(function(){i.focus()}),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button type='button'></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html("&#160;"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,a=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(a)||e.isArray(a)&&!a.length?(this.uiDialog.removeClass("ui-dialog-buttons"),void 0):(e.each(a,function(a,i){var r,s;i=e.isFunction(i)?{click:i,text:a}:i,i=e.extend({type:"button"},i),r=i.click,i.click=function(){r.apply(t.element[0],arguments)},s={icons:i.icons,text:i.showText},delete i.icons,delete i.showText,e("<button></button>",i).button(s).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var a=this,i=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(i,r){e(this).addClass("ui-dialog-dragging"),a._blockFrames(),a._trigger("dragStart",i,t(r))},drag:function(e,i){a._trigger("drag",e,t(i))},stop:function(r,s){var n=s.offset.left-a.document.scrollLeft(),o=s.offset.top-a.document.scrollTop();i.position={my:"left top",at:"left"+(n>=0?"+":"")+n+" "+"top"+(o>=0?"+":"")+o,of:a.window},e(this).removeClass("ui-dialog-dragging"),a._unblockFrames(),a._trigger("dragStop",r,t(s))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var a=this,i=this.options,r=i.resizable,s=this.uiDialog.css("position"),n="string"==typeof r?r:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:i.maxWidth,maxHeight:i.maxHeight,minWidth:i.minWidth,minHeight:this._minHeight(),handles:n,start:function(i,r){e(this).addClass("ui-dialog-resizing"),a._blockFrames(),a._trigger("resizeStart",i,t(r))},resize:function(e,i){a._trigger("resize",e,t(i))},stop:function(r,s){var n=a.uiDialog.offset(),o=n.left-a.document.scrollLeft(),d=n.top-a.document.scrollTop();i.height=a.uiDialog.height(),i.width=a.uiDialog.width(),i.position={my:"left top",at:"left"+(o>=0?"+":"")+o+" "+"top"+(d>=0?"+":"")+d,of:a.window},e(this).removeClass("ui-dialog-resizing"),a._unblockFrames(),a._trigger("resizeStop",r,t(s))}}).css("position",s)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._untrackInstance(),this._trackingInstances().unshift(this),this._focusedElement=e(t.target)}})},_untrackInstance:function(){var t=this._trackingInstances(),a=e.inArray(this,t);-1!==a&&t.splice(a,1)},_trackingInstances:function(){var e=this.document.data("ui-dialog-instances");return e||(e=[],this.document.data("ui-dialog-instances",e)),e},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(t){var a=this,i=!1,r={};e.each(t,function(e,t){a._setOption(e,t),e in a.sizeRelatedOptions&&(i=!0),e in a.resizableRelatedOptions&&(r[e]=t)}),i&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",r)},_setOption:function(e,t){var a,i,r=this.uiDialog;"dialogClass"===e&&r.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(a=r.is(":data(ui-draggable)"),a&&!t&&r.draggable("destroy"),!a&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(i=r.is(":data(ui-resizable)"),i&&!t&&r.resizable("destroy"),i&&"string"==typeof t&&r.resizable("option","handles",t),i||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,a,i=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),i.minWidth>i.width&&(i.width=i.minWidth),e=this.uiDialog.css({height:"auto",width:i.width}).outerHeight(),t=Math.max(0,i.minHeight-e),a="number"==typeof i.maxHeight?Math.max(0,i.maxHeight-e):"none","auto"===i.height?this.element.css({minHeight:t,maxHeight:a,height:"auto"}):this.element.height(Math.max(0,i.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=!0;this._delay(function(){t=!1}),this.document.data("ui-dialog-overlays")||this._on(this.document,{focusin:function(e){t||this._allowInteraction(e)||(e.preventDefault(),this._trackingInstances()[0]._focusTabbable())}}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1)}},_destroyOverlay:function(){if(this.options.modal&&this.overlay){var e=this.document.data("ui-dialog-overlays")-1;e?this.document.data("ui-dialog-overlays",e):this.document.off("focusin").removeData("ui-dialog-overlays"),this.overlay.remove(),this.overlay=null}}}),e.widget("ui.progressbar",{version:"1.11.0-beta.2",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return void 0===e?this.options.value:(this.options.value=this._constrainedValue(e),this._refreshValue(),void 0)},_constrainedValue:function(e){return void 0===e&&(e=this.options.value),this.indeterminate=e===!1,"number"!=typeof e&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){"max"===e&&(t=Math.max(this.min,t)),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,a=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass("ui-corner-right",t===this.options.max).width(a.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=e("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}}),e.widget("ui.selectmenu",{version:"1.11.0-beta.2",defaultElement:"<select>",options:{appendTo:null,disabled:null,icons:{button:"ui-icon-triangle-1-s"},position:{my:"left top",at:"left bottom",collision:"none"},width:null,change:null,close:null,focus:null,open:null,select:null},_create:function(){var e=this.element.uniqueId().attr("id");this.ids={element:e,button:e+"-button",menu:e+"-menu"},this._drawButton(),this._drawMenu(),this.options.disabled&&this.disable()},_drawButton:function(){var t=this,a=this.element.attr("tabindex");this.label=e("label[for='"+this.ids.element+"']").attr("for",this.ids.button),this._on(this.label,{click:function(e){this.button.focus(),e.preventDefault()}}),this.element.hide(),this.button=e("<span>",{"class":"ui-selectmenu-button ui-widget ui-state-default ui-corner-all",tabindex:a||this.options.disabled?-1:0,id:this.ids.button,role:"combobox","aria-expanded":"false","aria-autocomplete":"list","aria-owns":this.ids.menu,"aria-haspopup":"true"}).insertAfter(this.element),e("<span>",{"class":"ui-icon "+this.options.icons.button}).prependTo(this.button),this.buttonText=e("<span>",{"class":"ui-selectmenu-text"}).appendTo(this.button),this._setText(this.buttonText,this.element.find("option:selected").text()),this._setOption("width",this.options.width),this._on(this.button,this._buttonEvents),this.button.one("focusin",function(){t.menuItems||t._refreshMenu()}),this._hoverable(this.button),this._focusable(this.button)},_drawMenu:function(){var t=this;this.menu=e("<ul>",{"aria-hidden":"true","aria-labelledby":this.ids.button,id:this.ids.menu}),this.menuWrap=e("<div>",{"class":"ui-selectmenu-menu ui-front"}).append(this.menu).appendTo(this._appendTo()),this.menuInstance=this.menu.menu({role:"listbox",select:function(e,a){e.preventDefault(),t._select(a.item.data("ui-selectmenu-item"),e)},focus:function(e,a){var i=a.item.data("ui-selectmenu-item");null!=t.focusIndex&&i.index!==t.focusIndex&&(t._trigger("focus",e,{item:i}),t.isOpen||t._select(i,e)),t.focusIndex=i.index,t.button.attr("aria-activedescendant",t.menuItems.eq(i.index).attr("id"))}}).menu("instance"),this.menu.addClass("ui-corner-bottom").removeClass("ui-corner-all"),this.menuInstance._off(this.menu,"mouseleave"),this.menuInstance._closeOnDocumentClick=function(){return!1},this.menuInstance._isDivider=function(){return!1}},refresh:function(){this._refreshMenu(),this._setText(this.buttonText,this._getSelectedItem().text()),this._setOption("width",this.options.width)},_refreshMenu:function(){this.menu.empty();var e,t=this.element.find("option");t.length&&(this._parseOptions(t),this._renderMenu(this.menu,this.items),this.menuInstance.refresh(),this.menuItems=this.menu.find("li").not(".ui-selectmenu-optgroup"),e=this._getSelectedItem(),this.menuInstance.focus(null,e),this._setAria(e.data("ui-selectmenu-item")),this._setOption("disabled",this.element.prop("disabled")))},open:function(e){this.options.disabled||(this.menuItems?(this.menu.find(".ui-state-focus").removeClass("ui-state-focus"),this.menuInstance.focus(null,this._getSelectedItem())):this._refreshMenu(),this.isOpen=!0,this._toggleAttr(),this._resizeMenu(),this._position(),this._on(this.document,this._documentClick),this._trigger("open",e))},_position:function(){this.menuWrap.position(e.extend({of:this.button},this.options.position))},close:function(e){this.isOpen&&(this.isOpen=!1,this._toggleAttr(),this._off(this.document),this._trigger("close",e))},widget:function(){return this.button},menuWidget:function(){return this.menu},_renderMenu:function(t,a){var i=this,r="";e.each(a,function(a,s){s.optgroup!==r&&(e("<li>",{"class":"ui-selectmenu-optgroup ui-menu-divider"+(s.element.parent("optgroup").prop("disabled")?" ui-state-disabled":""),text:s.optgroup}).appendTo(t),r=s.optgroup),i._renderItemData(t,s)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-selectmenu-item",t)},_renderItem:function(t,a){var i=e("<li>");return a.disabled&&i.addClass("ui-state-disabled"),this._setText(i,a.label),i.appendTo(t)},_setText:function(e,t){t?e.text(t):e.html("&#160;")},_move:function(e,t){var a,i,r=".ui-menu-item";this.isOpen?a=this.menuItems.eq(this.focusIndex):(a=this.menuItems.eq(this.element[0].selectedIndex),r+=":not(.ui-state-disabled)"),i="first"===e||"last"===e?a["first"===e?"prevAll":"nextAll"](r).eq(-1):a[e+"All"](r).eq(0),i.length&&this.menuInstance.focus(t,i)},_getSelectedItem:function(){return this.menuItems.eq(this.element[0].selectedIndex)},_toggle:function(e){this[this.isOpen?"close":"open"](e)},_documentClick:{mousedown:function(t){this.isOpen&&(e(t.target).closest(".ui-selectmenu-menu, #"+this.ids.button).length||this.close(t))}},_buttonEvents:{click:"_toggle",keydown:function(t){var a=!0;switch(t.keyCode){case e.ui.keyCode.TAB:case e.ui.keyCode.ESCAPE:this.close(t),a=!1;break;case e.ui.keyCode.ENTER:this.isOpen&&this._selectFocusedItem(t);break;case e.ui.keyCode.UP:t.altKey?this._toggle(t):this._move("prev",t);break;case e.ui.keyCode.DOWN:t.altKey?this._toggle(t):this._move("next",t);break;case e.ui.keyCode.SPACE:this.isOpen?this._selectFocusedItem(t):this._toggle(t);break;case e.ui.keyCode.LEFT:this._move("prev",t);break;case e.ui.keyCode.RIGHT:this._move("next",t);break;case e.ui.keyCode.HOME:case e.ui.keyCode.PAGE_UP:this._move("first",t);break;case e.ui.keyCode.END:case e.ui.keyCode.PAGE_DOWN:this._move("last",t);break;default:this.menu.trigger(t),a=!1}a&&t.preventDefault()}},_selectFocusedItem:function(e){var t=this.menuItems.eq(this.focusIndex);t.hasClass("ui-state-disabled")||this._select(t.data("ui-selectmenu-item"),e)},_select:function(e,t){var a=this.element[0].selectedIndex;this.element[0].selectedIndex=e.index,this._setText(this.buttonText,e.label),this._setAria(e),this._trigger("select",t,{item:e}),e.index!==a&&this._trigger("change",t,{item:e}),this.close(t)},_setAria:function(e){var t=this.menuItems.eq(e.index).attr("id");this.button.attr({"aria-labelledby":t,"aria-activedescendant":t}),this.menu.attr("aria-activedescendant",t)},_setOption:function(e,t){"icons"===e&&this.button.find("span.ui-icon").removeClass(this.options.icons.button).addClass(t.button),this._super(e,t),"appendTo"===e&&this.menuWrap.appendTo(this._appendTo()),"disabled"===e&&(this.menuInstance.option("disabled",t),this.button.toggleClass("ui-state-disabled",t).attr("aria-disabled",t),this.element.prop("disabled",t),t?(this.button.attr("tabindex",-1),this.close()):this.button.attr("tabindex",0)),"width"===e&&(t||(t=this.element.outerWidth()),this.button.outerWidth(t))},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_toggleAttr:function(){this.button.toggleClass("ui-corner-top",this.isOpen).toggleClass("ui-corner-all",!this.isOpen).attr("aria-expanded",this.isOpen),this.menuWrap.toggleClass("ui-selectmenu-open",this.isOpen),this.menu.attr("aria-hidden",!this.isOpen)},_resizeMenu:function(){this.menu.outerWidth(Math.max(this.button.outerWidth(),this.menu.width("").outerWidth()+1))},_getCreateOptions:function(){return{disabled:this.element.prop("disabled")}},_parseOptions:function(t){var a=[];t.each(function(t,i){var r=e(i),s=r.parent("optgroup");a.push({element:r,index:t,value:r.attr("value"),label:r.text(),optgroup:s.attr("label")||"",disabled:s.prop("disabled")||r.prop("disabled")})}),this.items=a},_destroy:function(){this.menuWrap.remove(),this.button.remove(),this.element.show(),this.element.removeUniqueId(),this.label.attr("for",this.ids.element)}}),e.widget("ui.slider",e.ui.mouse,{version:"1.11.0-beta.2",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},numPages:5,_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var t,a,i=this.options,r=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),s="<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",n=[];for(a=i.values&&i.values.length||1,r.length>a&&(r.slice(a).remove(),r=r.slice(0,a)),t=r.length;a>t;t++)n.push(s);this.handles=r.add(e(n.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(t){e(this).data("ui-slider-handle-index",t)})},_createRange:function(){var t=this.options,a="";t.range?(t.range===!0&&(t.values?t.values.length&&2!==t.values.length?t.values=[t.values[0],t.values[0]]:e.isArray(t.values)&&(t.values=t.values.slice(0)):t.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=e("<div></div>").appendTo(this.element),a="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(a+("min"===t.range||"max"===t.range?" ui-slider-range-"+t.range:""))):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(t){var a,i,r,s,n,o,d,u,h=this,l=this.options;return l.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),a={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(a),r=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var a=Math.abs(i-h.values(t));(r>a||r===a&&(t===h._lastChangedValue||h.values(t)===l.min))&&(r=a,s=e(this),n=t)}),o=this._start(t,n),o===!1?!1:(this._mouseSliding=!0,this._handleIndex=n,s.addClass("ui-state-active").focus(),d=s.offset(),u=!e(t.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=u?{left:0,top:0}:{left:t.pageX-d.left-s.width()/2,top:t.pageY-d.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,n,i),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},a=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,a),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,a,i,r,s;return"horizontal"===this.orientation?(t=this.elementSize.width,a=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,a=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),i=a/t,i>1&&(i=1),0>i&&(i=0),"vertical"===this.orientation&&(i=1-i),r=this._valueMax()-this._valueMin(),s=this._valueMin()+i*r,this._trimAlignValue(s)},_start:function(e,t){var a={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(a.value=this.values(t),a.values=this.values()),this._trigger("start",e,a)},_slide:function(e,t,a){var i,r,s;this.options.values&&this.options.values.length?(i=this.values(t?0:1),2===this.options.values.length&&this.options.range===!0&&(0===t&&a>i||1===t&&i>a)&&(a=i),a!==this.values(t)&&(r=this.values(),r[t]=a,s=this._trigger("slide",e,{handle:this.handles[t],value:a,values:r}),i=this.values(t?0:1),s!==!1&&this.values(t,a))):a!==this.value()&&(s=this._trigger("slide",e,{handle:this.handles[t],value:a}),s!==!1&&this.value(a))},_stop:function(e,t){var a={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(a.value=this.values(t),a.values=this.values()),this._trigger("stop",e,a)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var a={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(a.value=this.values(t),a.values=this.values()),this._lastChangedValue=t,this._trigger("change",e,a)}},value:function(e){return arguments.length?(this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0),void 0):this._value()},values:function(t,a){var i,r,s;if(arguments.length>1)return this.options.values[t]=this._trimAlignValue(a),this._refreshValue(),this._change(null,t),void 0;if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();for(i=this.options.values,r=arguments[0],s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(r[s]),this._change(null,s);this._refreshValue()},_setOption:function(t,a){var i,r=0;switch("range"===t&&this.options.range===!0&&("min"===a?(this.options.value=this._values(0),this.options.values=null):"max"===a&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),e.isArray(this.options.values)&&(r=this.options.values.length),"disabled"===t&&this.element.toggleClass("ui-state-disabled",!!a),this._super(t,a),t){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),i=0;r>i;i+=1)this._change(null,i);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e)},_values:function(e){var t,a,i;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t);if(this.options.values&&this.options.values.length){for(a=this.options.values.slice(),i=0;a.length>i;i+=1)a[i]=this._trimAlignValue(a[i]);return a}return[]},_trimAlignValue:function(e){if(this._valueMin()>=e)return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,a=(e-this._valueMin())%t,i=e-a;return 2*Math.abs(a)>=t&&(i+=a>0?t:-t),parseFloat(i.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,a,i,r,s,n=this.options.range,o=this.options,d=this,u=this._animateOff?!1:o.animate,h={};this.options.values&&this.options.values.length?this.handles.each(function(i){a=100*((d.values(i)-d._valueMin())/(d._valueMax()-d._valueMin())),h["horizontal"===d.orientation?"left":"bottom"]=a+"%",e(this).stop(1,1)[u?"animate":"css"](h,o.animate),d.options.range===!0&&("horizontal"===d.orientation?(0===i&&d.range.stop(1,1)[u?"animate":"css"]({left:a+"%"},o.animate),1===i&&d.range[u?"animate":"css"]({width:a-t+"%"},{queue:!1,duration:o.animate})):(0===i&&d.range.stop(1,1)[u?"animate":"css"]({bottom:a+"%"},o.animate),1===i&&d.range[u?"animate":"css"]({height:a-t+"%"},{queue:!1,duration:o.animate}))),t=a}):(i=this.value(),r=this._valueMin(),s=this._valueMax(),a=s!==r?100*((i-r)/(s-r)):0,h["horizontal"===this.orientation?"left":"bottom"]=a+"%",this.handle.stop(1,1)[u?"animate":"css"](h,o.animate),"min"===n&&"horizontal"===this.orientation&&this.range.stop(1,1)[u?"animate":"css"]({width:a+"%"},o.animate),"max"===n&&"horizontal"===this.orientation&&this.range[u?"animate":"css"]({width:100-a+"%"},{queue:!1,duration:o.animate}),"min"===n&&"vertical"===this.orientation&&this.range.stop(1,1)[u?"animate":"css"]({height:a+"%"},o.animate),"max"===n&&"vertical"===this.orientation&&this.range[u?"animate":"css"]({height:100-a+"%"},{queue:!1,duration:o.animate}))},_handleEvents:{keydown:function(t){var a,i,r,s,n=e(t.target).data("ui-slider-handle-index");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(t.preventDefault(),!this._keySliding&&(this._keySliding=!0,e(t.target).addClass("ui-state-active"),a=this._start(t,n),a===!1))return}switch(s=this.options.step,i=r=this.options.values&&this.options.values.length?this.values(n):this.value(),t.keyCode){case e.ui.keyCode.HOME:r=this._valueMin();break;case e.ui.keyCode.END:r=this._valueMax();break;case e.ui.keyCode.PAGE_UP:r=this._trimAlignValue(i+(this._valueMax()-this._valueMin())/this.numPages);break;case e.ui.keyCode.PAGE_DOWN:r=this._trimAlignValue(i-(this._valueMax()-this._valueMin())/this.numPages);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(i===this._valueMax())return;r=this._trimAlignValue(i+s);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(i===this._valueMin())return;r=this._trimAlignValue(i-s)}this._slide(t,n,r)},keyup:function(t){var a=e(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,a),this._change(t,a),e(t.target).removeClass("ui-state-active"))}}}),e.widget("ui.spinner",{version:"1.11.0-beta.2",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},a=this.element;return e.each(["min","max","step"],function(e,i){var r=a.attr(i);void 0!==r&&r.length&&(t[i]=r)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e),void 0)},mousewheel:function(e,t){if(t){if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()}},"mousedown .ui-spinner-button":function(t){function a(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=i,this._delay(function(){this.previous=i}))}var i;i=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),a.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,a.call(this)}),this._start(t)!==!1&&this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){return e(t.currentTarget).hasClass("ui-state-active")?this._start(t)===!1?!1:(this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*e.height())&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var a=this.options,i=e.ui.keyCode;switch(t.keyCode){case i.UP:return this._repeat(null,1,t),!0;case i.DOWN:return this._repeat(null,-1,t),!0;case i.PAGE_UP:return this._repeat(null,a.page,t),!0;case i.PAGE_DOWN:return this._repeat(null,-a.page,t),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(e){return this.spinning||this._trigger("start",e)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(e,t,a){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,a)},e),this._spin(t*this.options.step,a)},_spin:function(e,t){var a=this.value()||0;this.counter||(this.counter=1),a=this._adjustValue(a+e*this._increment(this.counter)),this.spinning&&this._trigger("spin",t,{value:a})===!1||(this._value(a),this.counter++)},_increment:function(t){var a=this.options.incremental;return a?e.isFunction(a)?a(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return null!==this.options.min&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=""+e,a=t.indexOf(".");return-1===a?0:t.length-a-1},_adjustValue:function(e){var t,a,i=this.options;return t=null!==i.min?i.min:0,a=e-t,a=Math.round(a/i.step)*i.step,e=t+a,e=parseFloat(e.toFixed(this._precision())),null!==i.max&&e>i.max?i.max:null!==i.min&&i.min>e?i.min:e
+},_stop:function(e){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e))},_setOption:function(e,t){if("culture"===e||"numberFormat"===e){var a=this._parse(this.element.val());return this.options[e]=t,this.element.val(this._format(a)),void 0}("max"===e||"min"===e||"step"===e)&&"string"==typeof t&&(t=this._parse(t)),"icons"===e&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(t.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(t.down)),this._super(e,t),"disabled"===e&&(this.widget().toggleClass("ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable"))},_setOptions:o(function(e){this._super(e),this._value(this.element.val())}),_parse:function(e){return"string"==typeof e&&""!==e&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),""===e||isNaN(e)?null:e},_format:function(e){return""===e?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var e=this.value();return null===e?!1:e===this._adjustValue(e)},_value:function(e,t){var a;""!==e&&(a=this._parse(e),null!==a&&(t||(a=this._adjustValue(a)),e=this._format(a))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:o(function(e){this._stepUp(e)}),_stepUp:function(e){this._start()&&(this._spin((e||1)*this.options.step),this._stop())},stepDown:o(function(e){this._stepDown(e)}),_stepDown:function(e){this._start()&&(this._spin((e||1)*-this.options.step),this._stop())},pageUp:o(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:o(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){return arguments.length?(o(this._value).call(this,e),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),e.widget("ui.tabs",{version:"1.11.0-beta.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var e=/#.*$/;return function(t){var a,i;t=t.cloneNode(!1),a=t.href.replace(e,""),i=location.href.replace(e,"");try{a=decodeURIComponent(a)}catch(r){}try{i=decodeURIComponent(i)}catch(r){}return t.hash.length>1&&a===i}}(),_create:function(){var t=this,a=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",a.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),a.active=this._initialActive(),e.isArray(a.disabled)&&(a.disabled=e.unique(a.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(a.active):e(),this._refresh(),this.active.length&&this.load(a.active)},_initialActive:function(){var t=this.options.active,a=this.options.collapsible,i=location.hash.substring(1);return null===t&&(i&&this.tabs.each(function(a,r){return e(r).attr("aria-controls")===i?(t=a,!1):void 0}),null===t&&(t=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===t||-1===t)&&(t=this.tabs.length?0:!1)),t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),-1===t&&(t=a?!1:0)),!a&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var a=e(this.document[0].activeElement).closest("li"),i=this.tabs.index(a),r=!0;if(!this._handlePageNav(t)){switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:i++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:r=!1,i--;break;case e.ui.keyCode.END:i=this.anchors.length-1;break;case e.ui.keyCode.HOME:i=0;break;case e.ui.keyCode.SPACE:return t.preventDefault(),clearTimeout(this.activating),this._activate(i),void 0;case e.ui.keyCode.ENTER:return t.preventDefault(),clearTimeout(this.activating),this._activate(i===this.options.active?!1:i),void 0;default:return}t.preventDefault(),clearTimeout(this.activating),i=this._focusNextTab(i,r),t.ctrlKey||(a.attr("aria-selected","false"),this.tabs.eq(i).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",i)},this.delay))}},_panelKeydown:function(t){this._handlePageNav(t)||t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){return t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(t,a){function i(){return t>r&&(t=0),0>t&&(t=r),t}for(var r=this.tabs.length-1;-1!==e.inArray(i(),this.options.disabled);)t=a?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):"disabled"===e?(this._setupDisabled(t),void 0):(this._super(e,t),"collapsible"===e&&(this.element.toggleClass("ui-tabs-collapsible",t),t||this.options.active!==!1||this._activate(0)),"event"===e&&this._setupEvents(t),"heightStyle"===e&&this._setupHeightStyle(t),void 0)},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,a=this.tablist.children(":has(a[href])");t.disabled=e.map(a.filter(".ui-state-disabled"),function(e){return a.index(e)}),this._processTabs(),t.active!==!1&&this.anchors.length?this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=e()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(a,i){var r,s,n,o=e(i).uniqueId().attr("id"),d=e(i).closest("li"),u=d.attr("aria-controls");t._isLocal(i)?(r=i.hash,n=r.substring(1),s=t.element.find(t._sanitizeSelector(r))):(n=d.attr("aria-controls")||e({}).uniqueId()[0].id,r="#"+n,s=t.element.find(r),s.length||(s=t._createPanel(n),s.insertAfter(t.panels[a-1]||t.tablist)),s.attr("aria-live","polite")),s.length&&(t.panels=t.panels.add(s)),u&&d.data("ui-tabs-aria-controls",u),d.attr({"aria-controls":n,"aria-labelledby":o}),s.attr("aria-labelledby",o)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var a,i=0;a=this.tabs[i];i++)t===!0||-1!==e.inArray(i,t)?e(a).addClass("ui-state-disabled").attr("aria-disabled","true"):e(a).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var a={};t&&e.each(t.split(" "),function(e,t){a[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(e){e.preventDefault()}}),this._on(this.anchors,a),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var a,i=this.element.parent();"fill"===t?(a=i.height(),a-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=e(this),i=t.css("position");"absolute"!==i&&"fixed"!==i&&(a-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){a-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,a-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===t&&(a=0,this.panels.each(function(){a=Math.max(a,e(this).height("").height())}).height(a))},_eventHandler:function(t){var a=this.options,i=this.active,r=e(t.currentTarget),s=r.closest("li"),n=s[0]===i[0],o=n&&a.collapsible,d=o?e():this._getPanelForTab(s),u=i.length?this._getPanelForTab(i):e(),h={oldTab:i,oldPanel:u,newTab:o?e():s,newPanel:d};t.preventDefault(),s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||n&&!a.collapsible||this._trigger("beforeActivate",t,h)===!1||(a.active=o?!1:this.tabs.index(s),this.active=n?e():s,this.xhr&&this.xhr.abort(),u.length||d.length||e.error("jQuery UI Tabs: Mismatching fragment identifier."),d.length&&this.load(this.tabs.index(s),t),this._toggle(t,h))},_toggle:function(t,a){function i(){s.running=!1,s._trigger("activate",t,a)}function r(){a.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),n.length&&s.options.show?s._show(n,s.options.show,i):(n.show(),i())}var s=this,n=a.newPanel,o=a.oldPanel;this.running=!0,o.length&&this.options.hide?this._hide(o,this.options.hide,function(){a.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r()}):(a.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),o.hide(),r()),o.attr("aria-hidden","true"),a.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),n.length&&o.length?a.oldTab.attr("tabIndex",-1):n.length&&this.tabs.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),n.attr("aria-hidden","false"),a.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(t){var a,i=this._findActive(t);i[0]!==this.active[0]&&(i.length||(i=this.active),a=i.find(".ui-tabs-anchor")[0],this._eventHandler({target:a,currentTarget:a,preventDefault:e.noop}))},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return"string"==typeof e&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),a=t.data("ui-tabs-aria-controls");a?t.attr("aria-controls",a).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(t){var a=this.options.disabled;a!==!1&&(void 0===t?a=!1:(t=this._getIndex(t),a=e.isArray(a)?e.map(a,function(e){return e!==t?e:null}):e.map(this.tabs,function(e,a){return a!==t?a:null})),this._setupDisabled(a))},disable:function(t){var a=this.options.disabled;if(a!==!0){if(void 0===t)a=!0;else{if(t=this._getIndex(t),-1!==e.inArray(t,a))return;a=e.isArray(a)?e.merge([t],a).sort():[t]}this._setupDisabled(a)}},load:function(t,a){t=this._getIndex(t);var i=this,r=this.tabs.eq(t),s=r.find(".ui-tabs-anchor"),n=this._getPanelForTab(r),o={tab:r,panel:n};this._isLocal(s[0])||(this.xhr=e.ajax(this._ajaxSettings(s,a,o)),this.xhr&&"canceled"!==this.xhr.statusText&&(r.addClass("ui-tabs-loading"),n.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){n.html(e),i._trigger("load",a,o)},1)}).complete(function(e,t){setTimeout(function(){"abort"===t&&i.panels.stop(!1,!0),r.removeClass("ui-tabs-loading"),n.removeAttr("aria-busy"),e===i.xhr&&delete i.xhr},1)})))},_ajaxSettings:function(t,a,i){var r=this;return{url:t.attr("href"),beforeSend:function(t,s){return r._trigger("beforeLoad",a,e.extend({jqXHR:t,ajaxSettings:s},i))}}},_getPanelForTab:function(t){var a=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+a))}}),e.widget("ui.tooltip",{version:"1.11.0-beta.2",options:{content:function(){var t=e(this).attr("title")||"";return e("<a>").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_addDescribedBy:function(t,a){var i=(t.attr("aria-describedby")||"").split(/\s+/);i.push(a),t.data("ui-tooltip-id",a).attr("aria-describedby",e.trim(i.join(" ")))},_removeDescribedBy:function(t){var a=t.data("ui-tooltip-id"),i=(t.attr("aria-describedby")||"").split(/\s+/),r=e.inArray(a,i);-1!==r&&i.splice(r,1),t.removeData("ui-tooltip-id"),i=e.trim(i.join(" ")),i?t.attr("aria-describedby",i):t.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable(),this.liveRegion=e("<div>").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body)},_setOption:function(t,a){var i=this;return"disabled"===t?(this[a?"_disable":"_enable"](),this.options[t]=a,void 0):(this._super(t,a),"content"===t&&e.each(this.tooltips,function(e,t){i._updateContent(t)}),void 0)},_disable:function(){var t=this;e.each(this.tooltips,function(a,i){var r=e.Event("blur");r.target=r.currentTarget=i[0],t.close(r,!0)}),this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).removeAttr("title")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var a=this,i=e(t?t.target:this.element).closest(this.options.items);i.length&&!i.data("ui-tooltip-id")&&(i.attr("title")&&i.data("ui-tooltip-title",i.attr("title")),i.data("ui-tooltip-open",!0),t&&"mouseover"===t.type&&i.parents().each(function(){var t,i=e(this);i.data("ui-tooltip-open")&&(t=e.Event("blur"),t.target=t.currentTarget=this,a.close(t,!0)),i.attr("title")&&(i.uniqueId(),a.parents[this.id]={element:this,title:i.attr("title")},i.attr("title",""))}),this._updateContent(i,t))},_updateContent:function(e,t){var a,i=this.options.content,r=this,s=t?t.type:null;return"string"==typeof i?this._open(t,e,i):(a=i.call(e[0],function(a){e.data("ui-tooltip-open")&&r._delay(function(){t&&(t.type=s),this._open(t,e,a)})}),a&&this._open(t,e,a),void 0)},_open:function(t,a,i){function r(e){u.of=e,s.is(":hidden")||s.position(u)}var s,n,o,d,u=e.extend({},this.options.position);if(i){if(s=this._find(a),s.length)return s.find(".ui-tooltip-content").html(i),void 0;a.is("[title]")&&(t&&"mouseover"===t.type?a.attr("title",""):a.removeAttr("title")),s=this._tooltip(a),this._addDescribedBy(a,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.liveRegion.children().hide(),i.clone?(d=i.clone(),d.removeAttr("id").find("[id]").removeAttr("id")):d=i,e("<div>").html(d).appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:r}),r(t)):s.position(e.extend({of:a},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(o=this.delayedShow=setInterval(function(){s.is(":visible")&&(r(u.of),clearInterval(o))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),n={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var i=e.Event(t);i.currentTarget=a[0],this.close(i,!0)}}},a[0]!==this.element[0]&&(n.remove=function(){this._removeTooltip(s)}),t&&"mouseover"!==t.type||(n.mouseleave="close"),t&&"focusin"!==t.type||(n.focusout="close"),this._on(!0,a,n)}},close:function(t){var a=this,i=e(t?t.currentTarget:this.element),r=this._find(i);this.closing||(clearInterval(this.delayedShow),i.data("ui-tooltip-title")&&!i.attr("title")&&i.attr("title",i.data("ui-tooltip-title")),this._removeDescribedBy(i),r.stop(!0),this._hide(r,this.options.hide,function(){a._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&"mouseleave"===t.type&&e.each(this.parents,function(t,i){e(i.element).attr("title",i.title),delete a.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:r}),this.closing=!1)},_tooltip:function(t){var a=e("<div>").attr("role","tooltip").addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||"")),i=a.uniqueId().attr("id");return e("<div>").addClass("ui-tooltip-content").appendTo(a),a.appendTo(this.document[0].body),this.tooltips[i]=t,a},_find:function(t){var a=t.data("ui-tooltip-id");return a?e("#"+a):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(a,i){var r=e.Event("blur");r.target=r.currentTarget=i[0],t.close(r,!0),e("#"+a).remove(),i.data("ui-tooltip-title")&&(i.attr("title")||i.attr("title",i.data("ui-tooltip-title")),i.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}});var y="ui-effects-";e.effects={effect:{}},function(e,t){function a(e,t,a){var i=l[t.type]||{};return null==e?a||!t.def?null:t.def:(e=i.floor?~~e:parseFloat(e),isNaN(e)?t.def:i.mod?(e+i.mod)%i.mod:0>e?0:e>i.max?i.max:e)}function i(a){var i=u(),r=i._rgba=[];return a=a.toLowerCase(),p(d,function(e,s){var n,o=s.re.exec(a),d=o&&s.parse(o),u=s.space||"rgba";return d?(n=i[u](d),i[h[u].cache]=n[h[u].cache],r=i._rgba=n._rgba,!1):t}),r.length?("0,0,0,0"===r.join()&&e.extend(r,s.transparent),i):s[a]}function r(e,t,a){return a=(a+1)%1,1>6*a?e+6*(t-e)*a:1>2*a?t:2>3*a?e+6*(t-e)*(2/3-a):e}var s,n="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",o=/^([\-+])=\s*(\d+\.?\d*)/,d=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[2.55*e[1],2.55*e[2],2.55*e[3],e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],u=e.Color=function(t,a,i,r){return new e.Color.fn.parse(t,a,i,r)},h={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},l={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},m=u.support={},c=e("<p>")[0],p=e.each;c.style.cssText="background-color:rgba(1,1,1,.5)",m.rgba=c.style.backgroundColor.indexOf("rgba")>-1,p(h,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),u.fn=e.extend(u.prototype,{parse:function(r,n,o,d){if(r===t)return this._rgba=[null,null,null,null],this;(r.jquery||r.nodeType)&&(r=e(r).css(n),n=t);var l=this,m=e.type(r),c=this._rgba=[];return n!==t&&(r=[r,n,o,d],m="array"),"string"===m?this.parse(i(r)||s._default):"array"===m?(p(h.rgba.props,function(e,t){c[t.idx]=a(r[t.idx],t)}),this):"object"===m?(r instanceof u?p(h,function(e,t){r[t.cache]&&(l[t.cache]=r[t.cache].slice())}):p(h,function(t,i){var s=i.cache;p(i.props,function(e,t){if(!l[s]&&i.to){if("alpha"===e||null==r[e])return;l[s]=i.to(l._rgba)}l[s][t.idx]=a(r[e],t,!0)}),l[s]&&0>e.inArray(null,l[s].slice(0,3))&&(l[s][3]=1,i.from&&(l._rgba=i.from(l[s])))}),this):t},is:function(e){var a=u(e),i=!0,r=this;return p(h,function(e,s){var n,o=a[s.cache];return o&&(n=r[s.cache]||s.to&&s.to(r._rgba)||[],p(s.props,function(e,a){return null!=o[a.idx]?i=o[a.idx]===n[a.idx]:t})),i}),i},_space:function(){var e=[],t=this;return p(h,function(a,i){t[i.cache]&&e.push(a)}),e.pop()},transition:function(e,t){var i=u(e),r=i._space(),s=h[r],n=0===this.alpha()?u("transparent"):this,o=n[s.cache]||s.to(n._rgba),d=o.slice();return i=i[s.cache],p(s.props,function(e,r){var s=r.idx,n=o[s],u=i[s],h=l[r.type]||{};null!==u&&(null===n?d[s]=u:(h.mod&&(u-n>h.mod/2?n+=h.mod:n-u>h.mod/2&&(n-=h.mod)),d[s]=a((u-n)*t+n,r)))}),this[r](d)},blend:function(t){if(1===this._rgba[3])return this;var a=this._rgba.slice(),i=a.pop(),r=u(t)._rgba;return u(e.map(a,function(e,t){return(1-i)*r[t]+i*e}))},toRgbaString:function(){var t="rgba(",a=e.map(this._rgba,function(e,t){return null==e?t>2?1:0:e});return 1===a[3]&&(a.pop(),t="rgb("),t+a.join()+")"},toHslaString:function(){var t="hsla(",a=e.map(this.hsla(),function(e,t){return null==e&&(e=t>2?1:0),t&&3>t&&(e=Math.round(100*e)+"%"),e});return 1===a[3]&&(a.pop(),t="hsl("),t+a.join()+")"},toHexString:function(t){var a=this._rgba.slice(),i=a.pop();return t&&a.push(~~(255*i)),"#"+e.map(a,function(e){return e=(e||0).toString(16),1===e.length?"0"+e:e}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),u.fn.parse.prototype=u.fn,h.hsla.to=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t,a,i=e[0]/255,r=e[1]/255,s=e[2]/255,n=e[3],o=Math.max(i,r,s),d=Math.min(i,r,s),u=o-d,h=o+d,l=.5*h;return t=d===o?0:i===o?60*(r-s)/u+360:r===o?60*(s-i)/u+120:60*(i-r)/u+240,a=0===u?0:.5>=l?u/h:u/(2-h),[Math.round(t)%360,a,l,null==n?1:n]},h.hsla.from=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t=e[0]/360,a=e[1],i=e[2],s=e[3],n=.5>=i?i*(1+a):i+a-i*a,o=2*i-n;return[Math.round(255*r(o,n,t+1/3)),Math.round(255*r(o,n,t)),Math.round(255*r(o,n,t-1/3)),s]},p(h,function(i,r){var s=r.props,n=r.cache,d=r.to,h=r.from;u.fn[i]=function(i){if(d&&!this[n]&&(this[n]=d(this._rgba)),i===t)return this[n].slice();var r,o=e.type(i),l="array"===o||"object"===o?i:arguments,m=this[n].slice();return p(s,function(e,t){var i=l["object"===o?e:t.idx];null==i&&(i=m[t.idx]),m[t.idx]=a(i,t)}),h?(r=u(h(m)),r[n]=m,r):u(m)},p(s,function(t,a){u.fn[t]||(u.fn[t]=function(r){var s,n=e.type(r),d="alpha"===t?this._hsla?"hsla":"rgba":i,u=this[d](),h=u[a.idx];return"undefined"===n?h:("function"===n&&(r=r.call(this,h),n=e.type(r)),null==r&&a.empty?this:("string"===n&&(s=o.exec(r),s&&(r=h+parseFloat(s[2])*("+"===s[1]?1:-1))),u[a.idx]=r,this[d](u)))})})}),u.hook=function(t){var a=t.split(" ");p(a,function(t,a){e.cssHooks[a]={set:function(t,r){var s,n,o="";if("transparent"!==r&&("string"!==e.type(r)||(s=i(r)))){if(r=u(s||r),!m.rgba&&1!==r._rgba[3]){for(n="backgroundColor"===a?t.parentNode:t;(""===o||"transparent"===o)&&n&&n.style;)try{o=e.css(n,"backgroundColor"),n=n.parentNode}catch(d){}r=r.blend(o&&"transparent"!==o?o:"_default")}r=r.toRgbaString()}try{t.style[a]=r}catch(d){}}},e.fx.step[a]=function(t){t.colorInit||(t.start=u(t.elem,a),t.end=u(t.end),t.colorInit=!0),e.cssHooks[a].set(t.elem,t.start.transition(t.end,t.pos))}})},u.hook(n),e.cssHooks.borderColor={expand:function(e){var t={};return p(["Top","Right","Bottom","Left"],function(a,i){t["border"+i+"Color"]=e}),t}},s=e.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function t(t){var a,i,r=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,s={};if(r&&r.length&&r[0]&&r[r[0]])for(i=r.length;i--;)a=r[i],"string"==typeof r[a]&&(s[e.camelCase(a)]=r[a]);else for(a in r)"string"==typeof r[a]&&(s[a]=r[a]);return s}function a(t,a){var i,s,n={};for(i in a)s=a[i],t[i]!==s&&(r[i]||(e.fx.step[i]||!isNaN(parseFloat(s)))&&(n[i]=s));return n}var i=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,a){e.fx.step[a]=function(e){("none"!==e.end&&!e.setAttr||1===e.pos&&!e.setAttr)&&(jQuery.style(e.elem,a,e.end),e.setAttr=!0)}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e.effects.animateClass=function(r,s,n,o){var d=e.speed(s,n,o);return this.queue(function(){var s,n=e(this),o=n.attr("class")||"",u=d.children?n.find("*").addBack():n;u=u.map(function(){var a=e(this);return{el:a,start:t(this)}}),s=function(){e.each(i,function(e,t){r[t]&&n[t+"Class"](r[t])})},s(),u=u.map(function(){return this.end=t(this.el[0]),this.diff=a(this.start,this.end),this}),n.attr("class",o),u=u.map(function(){var t=this,a=e.Deferred(),i=e.extend({},d,{queue:!1,complete:function(){a.resolve(t)}});return this.el.animate(this.diff,i),a.promise()}),e.when.apply(e,u.get()).done(function(){s(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),d.complete.call(n[0])})})},e.fn.extend({addClass:function(t){return function(a,i,r,s){return i?e.effects.animateClass.call(this,{add:a},i,r,s):t.apply(this,arguments)}}(e.fn.addClass),removeClass:function(t){return function(a,i,r,s){return arguments.length>1?e.effects.animateClass.call(this,{remove:a},i,r,s):t.apply(this,arguments)}}(e.fn.removeClass),toggleClass:function(t){return function(a,i,r,s,n){return"boolean"==typeof i||void 0===i?r?e.effects.animateClass.call(this,i?{add:a}:{remove:a},r,s,n):t.apply(this,arguments):e.effects.animateClass.call(this,{toggle:a},i,r,s)}}(e.fn.toggleClass),switchClass:function(t,a,i,r,s){return e.effects.animateClass.call(this,{add:a,remove:t},i,r,s)}})}(),function(){function t(t,a,i,r){return e.isPlainObject(t)&&(a=t,t=t.effect),t={effect:t},null==a&&(a={}),e.isFunction(a)&&(r=a,i=null,a={}),("number"==typeof a||e.fx.speeds[a])&&(r=i,i=a,a={}),e.isFunction(i)&&(r=i,i=null),a&&e.extend(t,a),i=i||a.duration,t.duration=e.fx.off?0:"number"==typeof i?i:i in e.fx.speeds?e.fx.speeds[i]:e.fx.speeds._default,t.complete=r||a.complete,t}function a(t){return!t||"number"==typeof t||e.fx.speeds[t]?!0:"string"!=typeof t||e.effects.effect[t]?e.isFunction(t)?!0:"object"!=typeof t||t.effect?!1:!0:!0}e.extend(e.effects,{version:"1.11.0-beta.2",save:function(e,t){for(var a=0;t.length>a;a++)null!==t[a]&&e.data(y+t[a],e[0].style[t[a]])},restore:function(e,t){var a,i;for(i=0;t.length>i;i++)null!==t[i]&&(a=e.data(y+t[i]),void 0===a&&(a=""),e.css(t[i],a))},setMode:function(e,t){return"toggle"===t&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var a,i;switch(e[0]){case"top":a=0;break;case"middle":a=.5;break;case"bottom":a=1;break;default:a=e[0]/t.height}switch(e[1]){case"left":i=0;break;case"center":i=.5;break;case"right":i=1;break;default:i=e[1]/t.width}return{x:i,y:a}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var a={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},i=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),r={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(n){s=document.body}return t.wrap(i),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),i=t.parent(),"static"===t.css("position")?(i.css({position:"relative"}),t.css({position:"relative"})):(e.extend(a,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,i){a[i]=t.css(i),isNaN(parseInt(a[i],10))&&(a[i]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(r),i.css(a).show()},removeWrapper:function(t){var a=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===a||e.contains(t[0],a))&&e(a).focus()),t},setTransition:function(t,a,i,r){return r=r||{},e.each(a,function(e,a){var s=t.cssUnit(a);s[0]>0&&(r[a]=s[0]*i+s[1])}),r}}),e.fn.extend({effect:function(){function a(t){function a(){e.isFunction(s)&&s.call(r[0]),e.isFunction(t)&&t()}var r=e(this),s=i.complete,o=i.mode;(r.is(":hidden")?"hide"===o:"show"===o)?(r[o](),a()):n.call(r[0],i,a)}var i=t.apply(this,arguments),r=i.mode,s=i.queue,n=e.effects.effect[i.effect];return e.fx.off||!n?r?this[r](i.duration,i.complete):this.each(function(){i.complete&&i.complete.call(this)}):s===!1?this.each(a):this.queue(s||"fx",a)},show:function(e){return function(i){if(a(i))return e.apply(this,arguments);var r=t.apply(this,arguments);return r.mode="show",this.effect.call(this,r)}}(e.fn.show),hide:function(e){return function(i){if(a(i))return e.apply(this,arguments);var r=t.apply(this,arguments);return r.mode="hide",this.effect.call(this,r)}}(e.fn.hide),toggle:function(e){return function(i){if(a(i)||"boolean"==typeof i)return e.apply(this,arguments);var r=t.apply(this,arguments);return r.mode="toggle",this.effect.call(this,r)}}(e.fn.toggle),cssUnit:function(t){var a=this.css(t),i=[];return e.each(["em","px","%","pt"],function(e,t){a.indexOf(t)>0&&(i=[parseFloat(a),t])}),i}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,a){t[a]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return 0===e||1===e?e:-Math.pow(2,8*(e-1))*Math.sin((80*(e-1)-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){for(var t,a=4;((t=Math.pow(2,--a))-1)/11>e;);return 1/Math.pow(4,3-a)-7.5625*Math.pow((3*t-2)/22-e,2)}}),e.each(t,function(t,a){e.easing["easeIn"+t]=a,e.easing["easeOut"+t]=function(e){return 1-a(1-e)},e.easing["easeInOut"+t]=function(e){return.5>e?a(2*e)/2:1-a(-2*e+2)/2}})}(),e.effects,e.effects.effect.blind=function(t,a){var i,r,s,n=e(this),o=/up|down|vertical/,d=/up|left|vertical|horizontal/,u=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(n,t.mode||"hide"),l=t.direction||"up",m=o.test(l),c=m?"height":"width",p=m?"top":"left",f=d.test(l),g={},y="show"===h;
+n.parent().is(".ui-effects-wrapper")?e.effects.save(n.parent(),u):e.effects.save(n,u),n.show(),i=e.effects.createWrapper(n).css({overflow:"hidden"}),r=i[c](),s=parseFloat(i.css(p))||0,g[c]=y?r:0,f||(n.css(m?"bottom":"right",0).css(m?"top":"left","auto").css({position:"absolute"}),g[p]=y?s:r+s),y&&(i.css(c,0),f||i.css(p,s+r)),i.animate(g,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){"hide"===h&&n.hide(),e.effects.restore(n,u),e.effects.removeWrapper(n),a()}})},e.effects.effect.bounce=function(t,a){var i,r,s,n=e(this),o=["position","top","bottom","left","right","height","width"],d=e.effects.setMode(n,t.mode||"effect"),u="hide"===d,h="show"===d,l=t.direction||"up",m=t.distance,c=t.times||5,p=2*c+(h||u?1:0),f=t.duration/p,g=t.easing,y="up"===l||"down"===l?"top":"left",x="up"===l||"left"===l,v=n.queue(),T=v.length;for((h||u)&&o.push("opacity"),e.effects.save(n,o),n.show(),e.effects.createWrapper(n),m||(m=n["top"===y?"outerHeight":"outerWidth"]()/3),h&&(s={opacity:1},s[y]=0,n.css("opacity",0).css(y,x?2*-m:2*m).animate(s,f,g)),u&&(m/=Math.pow(2,c-1)),s={},s[y]=0,i=0;c>i;i++)r={},r[y]=(x?"-=":"+=")+m,n.animate(r,f,g).animate(s,f,g),m=u?2*m:m/2;u&&(r={opacity:0},r[y]=(x?"-=":"+=")+m,n.animate(r,f,g)),n.queue(function(){u&&n.hide(),e.effects.restore(n,o),e.effects.removeWrapper(n),a()}),T>1&&v.splice.apply(v,[1,0].concat(v.splice(T,p+1))),n.dequeue()},e.effects.effect.clip=function(t,a){var i,r,s,n=e(this),o=["position","top","bottom","left","right","height","width"],d=e.effects.setMode(n,t.mode||"hide"),u="show"===d,h=t.direction||"vertical",l="vertical"===h,m=l?"height":"width",c=l?"top":"left",p={};e.effects.save(n,o),n.show(),i=e.effects.createWrapper(n).css({overflow:"hidden"}),r="IMG"===n[0].tagName?i:n,s=r[m](),u&&(r.css(m,0),r.css(c,s/2)),p[m]=u?s:0,p[c]=u?0:s/2,r.animate(p,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){u||n.hide(),e.effects.restore(n,o),e.effects.removeWrapper(n),a()}})},e.effects.effect.drop=function(t,a){var i,r=e(this),s=["position","top","bottom","left","right","opacity","height","width"],n=e.effects.setMode(r,t.mode||"hide"),o="show"===n,d=t.direction||"left",u="up"===d||"down"===d?"top":"left",h="up"===d||"left"===d?"pos":"neg",l={opacity:o?1:0};e.effects.save(r,s),r.show(),e.effects.createWrapper(r),i=t.distance||r["top"===u?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(u,"pos"===h?-i:i),l[u]=(o?"pos"===h?"+=":"-=":"pos"===h?"-=":"+=")+i,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===n&&r.hide(),e.effects.restore(r,s),e.effects.removeWrapper(r),a()}})},e.effects.effect.explode=function(t,a){function i(){v.push(this),v.length===l*m&&r()}function r(){c.css({visibility:"visible"}),e(v).remove(),f||c.hide(),a()}var s,n,o,d,u,h,l=t.pieces?Math.round(Math.sqrt(t.pieces)):3,m=l,c=e(this),p=e.effects.setMode(c,t.mode||"hide"),f="show"===p,g=c.show().css("visibility","hidden").offset(),y=Math.ceil(c.outerWidth()/m),x=Math.ceil(c.outerHeight()/l),v=[];for(s=0;l>s;s++)for(d=g.top+s*x,h=s-(l-1)/2,n=0;m>n;n++)o=g.left+n*y,u=n-(m-1)/2,c.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-n*y,top:-s*x}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:y,height:x,left:o+(f?u*y:0),top:d+(f?h*x:0),opacity:f?0:1}).animate({left:o+(f?0:u*y),top:d+(f?0:h*x),opacity:f?1:0},t.duration||500,t.easing,i)},e.effects.effect.fade=function(t,a){var i=e(this),r=e.effects.setMode(i,t.mode||"toggle");i.animate({opacity:r},{queue:!1,duration:t.duration,easing:t.easing,complete:a})},e.effects.effect.fold=function(t,a){var i,r,s=e(this),n=["position","top","bottom","left","right","height","width"],o=e.effects.setMode(s,t.mode||"hide"),d="show"===o,u="hide"===o,h=t.size||15,l=/([0-9]+)%/.exec(h),m=!!t.horizFirst,c=d!==m,p=c?["width","height"]:["height","width"],f=t.duration/2,g={},y={};e.effects.save(s,n),s.show(),i=e.effects.createWrapper(s).css({overflow:"hidden"}),r=c?[i.width(),i.height()]:[i.height(),i.width()],l&&(h=parseInt(l[1],10)/100*r[u?0:1]),d&&i.css(m?{height:0,width:h}:{height:h,width:0}),g[p[0]]=d?r[0]:h,y[p[1]]=d?r[1]:0,i.animate(g,f,t.easing).animate(y,f,t.easing,function(){u&&s.hide(),e.effects.restore(s,n),e.effects.removeWrapper(s),a()})},e.effects.effect.highlight=function(t,a){var i=e(this),r=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(i,t.mode||"show"),n={backgroundColor:i.css("backgroundColor")};"hide"===s&&(n.opacity=0),e.effects.save(i,r),i.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(n,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===s&&i.hide(),e.effects.restore(i,r),a()}})},e.effects.effect.size=function(t,a){var i,r,s,n=e(this),o=["position","top","bottom","left","right","width","height","overflow","opacity"],d=["position","top","bottom","left","right","overflow","opacity"],u=["width","height","overflow"],h=["fontSize"],l=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],m=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],c=e.effects.setMode(n,t.mode||"effect"),p=t.restore||"effect"!==c,f=t.scale||"both",g=t.origin||["middle","center"],y=n.css("position"),x=p?o:d,v={height:0,width:0,outerHeight:0,outerWidth:0};"show"===c&&n.show(),i={height:n.height(),width:n.width(),outerHeight:n.outerHeight(),outerWidth:n.outerWidth()},"toggle"===t.mode&&"show"===c?(n.from=t.to||v,n.to=t.from||i):(n.from=t.from||("show"===c?v:i),n.to=t.to||("hide"===c?v:i)),s={from:{y:n.from.height/i.height,x:n.from.width/i.width},to:{y:n.to.height/i.height,x:n.to.width/i.width}},("box"===f||"both"===f)&&(s.from.y!==s.to.y&&(x=x.concat(l),n.from=e.effects.setTransition(n,l,s.from.y,n.from),n.to=e.effects.setTransition(n,l,s.to.y,n.to)),s.from.x!==s.to.x&&(x=x.concat(m),n.from=e.effects.setTransition(n,m,s.from.x,n.from),n.to=e.effects.setTransition(n,m,s.to.x,n.to))),("content"===f||"both"===f)&&s.from.y!==s.to.y&&(x=x.concat(h).concat(u),n.from=e.effects.setTransition(n,h,s.from.y,n.from),n.to=e.effects.setTransition(n,h,s.to.y,n.to)),e.effects.save(n,x),n.show(),e.effects.createWrapper(n),n.css("overflow","hidden").css(n.from),g&&(r=e.effects.getBaseline(g,i),n.from.top=(i.outerHeight-n.outerHeight())*r.y,n.from.left=(i.outerWidth-n.outerWidth())*r.x,n.to.top=(i.outerHeight-n.to.outerHeight)*r.y,n.to.left=(i.outerWidth-n.to.outerWidth)*r.x),n.css(n.from),("content"===f||"both"===f)&&(l=l.concat(["marginTop","marginBottom"]).concat(h),m=m.concat(["marginLeft","marginRight"]),u=o.concat(l).concat(m),n.find("*[width]").each(function(){var a=e(this),i={height:a.height(),width:a.width(),outerHeight:a.outerHeight(),outerWidth:a.outerWidth()};p&&e.effects.save(a,u),a.from={height:i.height*s.from.y,width:i.width*s.from.x,outerHeight:i.outerHeight*s.from.y,outerWidth:i.outerWidth*s.from.x},a.to={height:i.height*s.to.y,width:i.width*s.to.x,outerHeight:i.height*s.to.y,outerWidth:i.width*s.to.x},s.from.y!==s.to.y&&(a.from=e.effects.setTransition(a,l,s.from.y,a.from),a.to=e.effects.setTransition(a,l,s.to.y,a.to)),s.from.x!==s.to.x&&(a.from=e.effects.setTransition(a,m,s.from.x,a.from),a.to=e.effects.setTransition(a,m,s.to.x,a.to)),a.css(a.from),a.animate(a.to,t.duration,t.easing,function(){p&&e.effects.restore(a,u)})})),n.animate(n.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){0===n.to.opacity&&n.css("opacity",n.from.opacity),"hide"===c&&n.hide(),e.effects.restore(n,x),p||("static"===y?n.css({position:"relative",top:n.to.top,left:n.to.left}):e.each(["top","left"],function(e,t){n.css(t,function(t,a){var i=parseInt(a,10),r=e?n.to.left:n.to.top;return"auto"===a?r+"px":i+r+"px"})})),e.effects.removeWrapper(n),a()}})},e.effects.effect.scale=function(t,a){var i=e(this),r=e.extend(!0,{},t),s=e.effects.setMode(i,t.mode||"effect"),n=parseInt(t.percent,10)||(0===parseInt(t.percent,10)?0:"hide"===s?0:100),o=t.direction||"both",d=t.origin,u={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()},h={y:"horizontal"!==o?n/100:1,x:"vertical"!==o?n/100:1};r.effect="size",r.queue=!1,r.complete=a,"effect"!==s&&(r.origin=d||["middle","center"],r.restore=!0),r.from=t.from||("show"===s?{height:0,width:0,outerHeight:0,outerWidth:0}:u),r.to={height:u.height*h.y,width:u.width*h.x,outerHeight:u.outerHeight*h.y,outerWidth:u.outerWidth*h.x},r.fade&&("show"===s&&(r.from.opacity=0,r.to.opacity=1),"hide"===s&&(r.from.opacity=1,r.to.opacity=0)),i.effect(r)},e.effects.effect.puff=function(t,a){var i=e(this),r=e.effects.setMode(i,t.mode||"hide"),s="hide"===r,n=parseInt(t.percent,10)||150,o=n/100,d={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:r,complete:a,percent:s?n:100,from:s?d:{height:d.height*o,width:d.width*o,outerHeight:d.outerHeight*o,outerWidth:d.outerWidth*o}}),i.effect(t)},e.effects.effect.pulsate=function(t,a){var i,r=e(this),s=e.effects.setMode(r,t.mode||"show"),n="show"===s,o="hide"===s,d=n||"hide"===s,u=2*(t.times||5)+(d?1:0),h=t.duration/u,l=0,m=r.queue(),c=m.length;for((n||!r.is(":visible"))&&(r.css("opacity",0).show(),l=1),i=1;u>i;i++)r.animate({opacity:l},h,t.easing),l=1-l;r.animate({opacity:l},h,t.easing),r.queue(function(){o&&r.hide(),a()}),c>1&&m.splice.apply(m,[1,0].concat(m.splice(c,u+1))),r.dequeue()},e.effects.effect.shake=function(t,a){var i,r=e(this),s=["position","top","bottom","left","right","height","width"],n=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",d=t.distance||20,u=t.times||3,h=2*u+1,l=Math.round(t.duration/h),m="up"===o||"down"===o?"top":"left",c="up"===o||"left"===o,p={},f={},g={},y=r.queue(),x=y.length;for(e.effects.save(r,s),r.show(),e.effects.createWrapper(r),p[m]=(c?"-=":"+=")+d,f[m]=(c?"+=":"-=")+2*d,g[m]=(c?"-=":"+=")+2*d,r.animate(p,l,t.easing),i=1;u>i;i++)r.animate(f,l,t.easing).animate(g,l,t.easing);r.animate(f,l,t.easing).animate(p,l/2,t.easing).queue(function(){"hide"===n&&r.hide(),e.effects.restore(r,s),e.effects.removeWrapper(r),a()}),x>1&&y.splice.apply(y,[1,0].concat(y.splice(x,h+1))),r.dequeue()},e.effects.effect.slide=function(t,a){var i,r=e(this),s=["position","top","bottom","left","right","width","height"],n=e.effects.setMode(r,t.mode||"show"),o="show"===n,d=t.direction||"left",u="up"===d||"down"===d?"top":"left",h="up"===d||"left"===d,l={};e.effects.save(r,s),r.show(),i=t.distance||r["top"===u?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(u,h?isNaN(i)?"-"+i:-i:i),l[u]=(o?h?"+=":"-=":h?"-=":"+=")+i,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===n&&r.hide(),e.effects.restore(r,s),e.effects.removeWrapper(r),a()}})},e.effects.effect.transfer=function(t,a){var i=e(this),r=e(t.to),s="fixed"===r.css("position"),n=e("body"),o=s?n.scrollTop():0,d=s?n.scrollLeft():0,u=r.offset(),h={top:u.top-o,left:u.left-d,height:r.innerHeight(),width:r.innerWidth()},l=i.offset(),m=e("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(t.className).css({top:l.top-o,left:l.left-d,height:i.innerHeight(),width:i.innerWidth(),position:s?"fixed":"absolute"}).animate(h,t.duration,t.easing,function(){m.remove(),a()})}});
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/odl/list_mounts.js b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/odl/list_mounts.js
new file mode 100644 (file)
index 0000000..bfd561a
--- /dev/null
@@ -0,0 +1,22 @@
+//constructs a table of mount points via a json response
+//Loads the table into the given dom.
+var loadMountList = function( dom ) {
+    dom.empty();
+    dom.append( "<p>Loading. Please wait...</p>" );
+    $.ajax( {
+        url: "/apidoc/apis/mounts",
+        datatype: 'jsonp',
+        success: function( strData ){
+            var myData = strData;
+            var list = $( "<table></table>" );
+            for( var key in myData )
+            {
+                list.append( "<tr><td><a href=\"#\" onclick=\"loadMount(" + 
+                                        myData[key].id + ", '" + myData[key].instance + "')\">" +
+                                        myData[key].instance + "</a></td></tr>");
+            }
+            dom.empty();
+            dom.append( list );
+        }
+    } );
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/odl/swagger.js b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/odl/swagger.js
new file mode 100644 (file)
index 0000000..58584e5
--- /dev/null
@@ -0,0 +1,44 @@
+
+//There can only be a single swagger UI in a dom tree
+//at a time - this is a limitation of the swagger API
+//This method takes a URL which is the root of the swagger
+//documentation, as well as the ID of the dom where we should
+//load the swagger UI.
+//See the swagger documentation for more information.
+var loadSwagger = function(url, dom_id) {
+    $("#" + dom_id).empty();
+    $("#" + dom_id).append("Loading " + url);
+    window.swaggerUi = new SwaggerUi({
+        url : url,
+        dom_id : dom_id,
+        supportedSubmitMethods : [ 'get', 'post', 'put', 'delete' ],
+        onComplete : function(swaggerApi, swaggerUi) {
+            if (console) {
+                console.log("Loaded SwaggerUI")
+            }
+            $('pre code').each(function(i, e) {
+                hljs.highlightBlock(e)
+            });
+        },
+        onFailure : function(data) {
+            if (console) {
+                console.log("Unable to Load SwaggerUI");
+                console.log(data);
+            }
+        },
+        docExpansion : "none"
+    });
+
+    $('#input_apiKey').change(
+            function() {
+                var key = $('#input_apiKey')[0].value;
+                console.log("key: " + key);
+                if (key && key.trim() != "") {
+                    console.log("added key " + key);
+                    window.authorizations
+                            .add("key", new ApiKeyAuthorization("api_key",
+                                    key, "query"));
+                }
+            });
+    window.swaggerUi.load();
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java b/opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java
new file mode 100644 (file)
index 0000000..8390a38
--- /dev/null
@@ -0,0 +1,137 @@
+package org.opendaylight.controller.sal.rest.doc.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.ws.rs.core.UriInfo;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.rest.doc.swagger.Api;
+import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
+import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
+import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
+import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+import com.google.common.base.Preconditions;
+
+/**
+ *
+ */
+public class ApiDocGeneratorTest {
+
+    public static final String HTTP_HOST = "http://host";
+    private ApiDocGenerator generator;
+    private DocGenTestHelper helper;
+
+    @Before
+    public void setUp() throws Exception {
+        generator = new ApiDocGenerator();
+        helper = new DocGenTestHelper();
+        helper.setUp();
+    }
+
+    @After
+    public void after() throws Exception {
+    }
+
+    /**
+     * Method: getApiDeclaration(String module, String revision, UriInfo
+     * uriInfo)
+     */
+    @Test
+    public void testGetModuleDoc() throws Exception {
+        Preconditions.checkArgument(helper.getModules() != null, "No modules found");
+
+        for (Entry<File, Module> m : helper.getModules().entrySet()) {
+            if (m.getKey().getAbsolutePath().endsWith("toaster_short.yang")) {
+                ApiDeclaration doc = generator.getSwaggerDocSpec(m.getValue(),
+                        "http://localhost:8080/restconf", "");
+                validateToaster(doc);
+                Assert.assertNotNull(doc);
+            }
+        }
+    }
+
+    private void validateToaster(ApiDeclaration doc) throws Exception {
+        Set<String> expectedUrls = new TreeSet<>(Arrays.asList(new String[] {
+                "/config/toaster2:toaster/", "/operational/toaster2:toaster/",
+                "/operations/toaster2:cancel-toast", "/operations/toaster2:make-toast",
+                "/operations/toaster2:restock-toaster" }));
+
+        Set<String> actualUrls = new TreeSet<>();
+
+        Api configApi = null;
+        for (Api api : doc.getApis()) {
+            actualUrls.add(api.getPath());
+            if (api.getPath().contains("/config/toaster2:toaster/")) {
+                configApi = api;
+            }
+        }
+
+        boolean containsAll = actualUrls.containsAll(expectedUrls);
+        if (!containsAll) {
+            expectedUrls.removeAll(actualUrls);
+            fail("Missing expected urls: " + expectedUrls);
+        }
+
+        Set<String> expectedConfigMethods = new TreeSet<>(Arrays.asList(new String[] { "GET",
+                "PUT", "DELETE" }));
+        Set<String> actualConfigMethods = new TreeSet<>();
+        for (Operation oper : configApi.getOperations()) {
+            actualConfigMethods.add(oper.getMethod());
+        }
+
+        containsAll = actualConfigMethods.containsAll(expectedConfigMethods);
+        if (!containsAll) {
+            expectedConfigMethods.removeAll(actualConfigMethods);
+            fail("Missing expected method on config API: " + expectedConfigMethods);
+        }
+        // TODO: we should really do some more validation of the
+        // documentation...
+        /**
+         * Missing validation: Explicit validation of URLs, and their methods
+         * Input / output models.
+         */
+    }
+
+    @Test
+    public void testGetResourceListing() throws Exception {
+        UriInfo info = helper.createMockUriInfo(HTTP_HOST);
+        SchemaService mockSchemaService = helper.createMockSchemaService();
+
+        generator.setSchemaService(mockSchemaService);
+
+        ResourceList resourceListing = generator.getResourceListing(info);
+
+        Resource toaster = null;
+        Resource toaster2 = null;
+        for (Resource r : resourceListing.getApis()) {
+            String path = r.getPath();
+            if (path.contains("toaster2")) {
+                toaster2 = r;
+            } else if (path.contains("toaster")) {
+                toaster = r;
+            }
+        }
+
+        assertNotNull(toaster2);
+        assertNotNull(toaster);
+
+        assertEquals(HTTP_HOST + "/toaster(2009-11-20)", toaster.getPath());
+        assertEquals(HTTP_HOST + "/toaster2(2009-11-20)", toaster2.getPath());
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/DocGenTestHelper.java b/opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/DocGenTestHelper.java
new file mode 100644 (file)
index 0000000..0f15d00
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.rest.doc.impl;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
+
+public class DocGenTestHelper {
+
+    private Map<File, Module> modules;
+    private ObjectMapper mapper;
+
+    public Map<File, Module> loadModules(String resourceDirectory) throws FileNotFoundException,
+            URISyntaxException {
+
+        URI resourceDirUri = getClass().getResource(resourceDirectory).toURI();
+        final YangModelParser parser = new YangParserImpl();
+        final File testDir = new File(resourceDirUri);
+        final String[] fileList = testDir.list();
+        final List<File> testFiles = new ArrayList<>();
+        if (fileList == null) {
+            throw new FileNotFoundException(resourceDirectory.toString());
+        }
+        for (String fileName : fileList) {
+
+            testFiles.add(new File(testDir, fileName));
+        }
+        return parser.parseYangModelsMapped(testFiles);
+    }
+
+    public Map<File, Module> getModules() {
+        return modules;
+    }
+
+    public void setUp() throws Exception {
+        modules = loadModules("/yang");
+        mapper = new ObjectMapper();
+        mapper.registerModule(new JsonOrgModule());
+        mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
+    }
+
+    public SchemaService createMockSchemaService() {
+        return createMockSchemaService(null);
+    }
+
+    public SchemaService createMockSchemaService(SchemaContext mockContext) {
+        if (mockContext == null) {
+            mockContext = createMockSchemaContext();
+        }
+
+        SchemaService mockSchemaService = mock(SchemaService.class);
+        when(mockSchemaService.getGlobalContext()).thenReturn(mockContext);
+        return mockSchemaService;
+    }
+
+    public SchemaContext createMockSchemaContext() {
+        SchemaContext mockContext = mock(SchemaContext.class);
+        when(mockContext.getModules()).thenReturn(new HashSet<Module>(modules.values()));
+
+        final ArgumentCaptor<String> moduleCapture = ArgumentCaptor.forClass(String.class);
+        final ArgumentCaptor<Date> dateCapture = ArgumentCaptor.forClass(Date.class);
+        when(mockContext.findModuleByName(moduleCapture.capture(), dateCapture.capture())).then(
+                new Answer<Module>() {
+                    @Override
+                    public Module answer(InvocationOnMock invocation) throws Throwable {
+                        String module = moduleCapture.getValue();
+                        Date date = dateCapture.getValue();
+                        for (Module m : modules.values()) {
+                            if (m.getName().equals(module) && m.getRevision().equals(date)) {
+                                return m;
+                            }
+                        }
+                        return null;
+                    }
+                });
+        return mockContext;
+    }
+
+    public UriInfo createMockUriInfo(String urlPrefix) throws URISyntaxException {
+        final URI uri = new URI(urlPrefix);
+
+        UriBuilder mockBuilder = mock(UriBuilder.class);
+
+        final ArgumentCaptor<String> subStringCapture = ArgumentCaptor.forClass(String.class);
+        when(mockBuilder.path(subStringCapture.capture())).thenReturn(mockBuilder);
+        when(mockBuilder.build()).then(new Answer<URI>() {
+            @Override
+            public URI answer(InvocationOnMock invocation) throws Throwable {
+                return URI.create(uri + "/" + subStringCapture.getValue());
+            }
+        });
+
+        UriInfo info = mock(UriInfo.class);
+
+        when(info.getRequestUriBuilder()).thenReturn(mockBuilder);
+        when(info.getBaseUri()).thenReturn(uri);
+        return info;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/DocGeneratorTest.java b/opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/DocGeneratorTest.java
deleted file mode 100644 (file)
index 264bc67..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.opendaylight.controller.sal.rest.doc.impl;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
-import com.google.common.base.Preconditions;
-import junit.framework.Assert;
-import org.junit.Test;
-import org.junit.Before;
-import org.junit.After;
-import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- *
- */
-public class DocGeneratorTest {
-
-  private Set<Module> modules;
-  private ObjectMapper mapper;
-
-  public Set<Module> loadModules(String resourceDirectory) throws FileNotFoundException, URISyntaxException {
-
-    URI resourceDirUri = getClass().getResource(resourceDirectory).toURI();
-    final YangModelParser parser = new YangParserImpl();
-    final File testDir = new File(resourceDirUri);
-    final String[] fileList = testDir.list();
-    final List<File> testFiles = new ArrayList<>();
-    if (fileList == null) {
-      throw new FileNotFoundException(resourceDirectory.toString());
-    }
-    for (String fileName : fileList) {
-
-      testFiles.add(new File(testDir, fileName));
-    }
-    return parser.parseYangModels(testFiles);
-  }
-
-  @Before
-  public void before() throws Exception {
-    modules = loadModules("/yang");
-    mapper = new ObjectMapper();
-    mapper.registerModule(new JsonOrgModule());
-  }
-
-  @After
-  public void after() throws Exception {
-  }
-
-  /**
-   * Method: getApiDeclaration(String module, String revision, UriInfo uriInfo)
-   */
-  @Test
-  public void testGetModuleDoc() throws Exception {
-    Preconditions.checkArgument(modules != null, "No modules found");
-
-    for (Module m : modules){
-      ApiDeclaration doc = ApiDocGenerator.getInstance().getSwaggerDocSpec(m, "http://localhost:8080/restconf");
-      Assert.assertNotNull(doc);
-    }
-  }
-
-}
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/MountPointSwaggerTest.java b/opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/MountPointSwaggerTest.java
new file mode 100644 (file)
index 0000000..a2e2939
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.rest.doc.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.ws.rs.core.UriInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.rest.doc.mountpoints.MountPointSwagger;
+import org.opendaylight.controller.sal.rest.doc.swagger.Api;
+import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
+import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
+import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
+import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class MountPointSwaggerTest {
+
+    private static final String HTTP_URL = "http://localhost/path";
+    private static final InstanceIdentifier instanceId = InstanceIdentifier.builder()
+            .node(QName.create("nodes"))
+            .nodeWithKey(QName.create("node"), QName.create("id"), "123").build();
+    private static final String INSTANCE_URL = "nodes/node/123/";
+    private MountPointSwagger swagger;
+    private DocGenTestHelper helper;
+
+    @Before
+    public void setUp() throws Exception {
+        swagger = new MountPointSwagger();
+        helper = new DocGenTestHelper();
+        helper.setUp();
+    }
+
+    @Test()
+    public void testGetResourceListBadIid() throws Exception {
+        UriInfo mockInfo = helper.createMockUriInfo(HTTP_URL);
+
+        assertEquals(null, swagger.getResourceList(mockInfo, 1L));
+    }
+
+    @Test()
+    public void getInstanceIdentifiers() throws Exception {
+        UriInfo mockInfo = setUpSwaggerForDocGeneration();
+
+        assertEquals(0, swagger.getInstanceIdentifiers().size());
+        swagger.onMountPointCreated(instanceId); // add this ID into the list of
+                                                 // mount points
+        assertEquals(1, swagger.getInstanceIdentifiers().size());
+        assertEquals((Long) 1L, swagger.getInstanceIdentifiers().entrySet().iterator().next()
+                .getValue());
+        assertEquals(INSTANCE_URL, swagger.getInstanceIdentifiers().entrySet().iterator().next()
+                .getKey());
+        swagger.onMountPointRemoved(instanceId); // remove ID from list of mount
+                                                 // points
+        assertEquals(0, swagger.getInstanceIdentifiers().size());
+    }
+
+    @Test
+    public void testGetResourceListGoodId() throws Exception {
+        UriInfo mockInfo = setUpSwaggerForDocGeneration();
+        swagger.onMountPointCreated(instanceId); // add this ID into the list of
+                                                 // mount points
+        ResourceList resourceList = swagger.getResourceList(mockInfo, 1L);
+
+        Resource dataStoreResource = null;
+        for (Resource r : resourceList.getApis()) {
+            if (r.getPath().endsWith("/Datastores(-)")) {
+                dataStoreResource = r;
+            }
+        }
+        assertNotNull("Failed to find data store resource", dataStoreResource);
+    }
+
+    @Test
+    public void testGetDataStoreApi() throws Exception {
+        UriInfo mockInfo = setUpSwaggerForDocGeneration();
+        swagger.onMountPointCreated(instanceId); // add this ID into the list of
+                                                 // mount points
+        ApiDeclaration mountPointApi = swagger.getMountPointApi(mockInfo, 1L, "Datastores", "-");
+        assertNotNull("failed to find Datastore API", mountPointApi);
+        List<Api> apis = mountPointApi.getApis();
+        assertEquals("Unexpected api list size", 3, apis.size());
+
+        Set<String> actualApis = new TreeSet<>();
+        for (Api api : apis) {
+            actualApis.add(api.getPath());
+            List<Operation> operations = api.getOperations();
+            assertEquals("unexpected operation size on " + api.getPath(), 1, operations.size());
+            assertEquals("unexpected operation method " + api.getPath(), "GET", operations.get(0)
+                    .getMethod());
+            assertNotNull("expected non-null desc on " + api.getPath(), operations.get(0)
+                    .getNotes());
+        }
+        Set<String> expectedApis = new TreeSet<>(Arrays.asList(new String[] {
+                "/config/" + INSTANCE_URL + "yang-ext:mount/",
+                "/operational/" + INSTANCE_URL + "yang-ext:mount/",
+                "/operations/" + INSTANCE_URL + "yang-ext:mount/", }));
+        assertEquals(expectedApis, actualApis);
+    }
+
+    protected UriInfo setUpSwaggerForDocGeneration() throws URISyntaxException {
+        UriInfo mockInfo = helper.createMockUriInfo(HTTP_URL);
+        // We are sharing the global schema service and the mount schema service
+        // in our test.
+        // OK for testing - real thing would have seperate instances.
+        SchemaContext context = helper.createMockSchemaContext();
+        SchemaService schemaService = helper.createMockSchemaService(context);
+
+        MountProvisionInstance mountPoint = mock(MountProvisionInstance.class);
+        when(mountPoint.getSchemaContext()).thenReturn(context);
+
+        MountProvisionService service = mock(MountProvisionService.class);
+        when(service.getMountPoint(instanceId)).thenReturn(mountPoint);
+        swagger.setMountService(service);
+        swagger.setGlobalSchema(schemaService);
+
+        return mockInfo;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_short.yang b/opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_short.yang
new file mode 100644 (file)
index 0000000..9995a8f
--- /dev/null
@@ -0,0 +1,200 @@
+  module toaster2 {
+
+    yang-version 1;
+
+    namespace
+      "http://netconfcentral.org/ns/toaster";
+
+    prefix toast;
+
+    organization "Netconf Central";
+
+    contact
+      "Andy Bierman <andy@netconfcentral.org>";
+
+    description
+      "YANG version of the TOASTER-MIB.";
+
+    revision "2009-11-20" {
+      description
+        "Toaster module in progress.";
+    }
+
+
+    identity toast-type {
+      description
+        "Base for all bread types supported by the toaster.
+           New bread types not listed here nay be added in the
+           future.";
+    }
+
+    identity white-bread {
+      base toast:toast-type;
+      description "White bread.";
+    }
+
+    identity wheat-bread {
+      base toast-type;
+      description "Wheat bread.";
+    }
+
+    identity wonder-bread {
+      base toast-type;
+      description "Wonder bread.";
+    }
+
+    identity frozen-waffle {
+      base toast-type;
+      description "Frozen waffle.";
+    }
+
+    identity frozen-bagel {
+      base toast-type;
+      description "Frozen bagel.";
+    }
+
+    identity hash-brown {
+      base toast-type;
+      description "Hash browned potatos.";
+    }
+
+    typedef DisplayString {
+      type string {
+        length "0 .. 255";
+      }
+      description
+        "YANG version of the SMIv2 DisplayString TEXTUAL-CONVENTION.";
+      reference
+        "RFC 2579, section 2.";
+
+    }
+
+    container toaster {
+      presence
+        "Indicates the toaster service is available";
+      description
+        "Top-level container for all toaster database objects.";
+      leaf toasterManufacturer {
+        type DisplayString;
+        config false;
+        mandatory true;
+        description
+          "The name of the toaster's manufacturer. For instance,
+                Microsoft Toaster.";
+      }
+
+      leaf toasterModelNumber {
+        type DisplayString;
+        config false;
+        mandatory true;
+        description
+          "The name of the toaster's model. For instance,
+               Radiant Automatic.";
+      }
+
+      leaf toasterStatus {
+        type enumeration {
+          enum "up" {
+            value 1;
+            description
+              "The toaster knob position is up.
+                      No toast is being made now.";
+          }
+          enum "down" {
+            value 2;
+            description
+              "The toaster knob position is down.
+                      Toast is being made now.";
+          }
+        }
+        config false;
+        mandatory true;
+        description
+          "This variable indicates the current state of
+               the toaster.";
+      }
+
+      leaf darknessFactor {
+        type uint32;
+        config true;
+        default 1000;
+        description
+          "The darkness factor. Basically, the number of ms to multiple the doneness value by.";
+      }
+    }  // container toaster
+
+    rpc make-toast {
+      description
+        "Make some toast.
+           The toastDone notification will be sent when
+           the toast is finished.
+           An 'in-use' error will be returned if toast
+           is already being made.
+           A 'resource-denied' error will be returned
+           if the toaster service is disabled.";
+      input {
+        leaf toasterDoneness {
+          type uint32 {
+            range "1 .. 10";
+          }
+          default '5';
+          description
+            "This variable controls how well-done is the
+                   ensuing toast. It should be on a scale of 1 to 10.
+                   Toast made at 10 generally is considered unfit
+                   for human consumption; toast made at 1 is warmed
+                   lightly.";
+        }
+
+        leaf toasterToastType {
+          type identityref {
+            base toast:toast-type;
+          }
+          default 'wheat-bread';
+          description
+            "This variable informs the toaster of the type of
+                   material that is being toasted. The toaster
+                   uses this information, combined with
+                   toasterDoneness, to compute for how
+                   long the material must be toasted to achieve
+                   the required doneness.";
+        }
+      }
+    }  // rpc make-toast
+
+    rpc cancel-toast {
+      description
+        "Stop making toast, if any is being made.
+           A 'resource-denied' error will be returned
+           if the toaster service is disabled.";
+    }  // rpc cancel-toast
+
+    rpc restock-toaster {
+        description
+          "Restocks the toaster with the amount of bread specified.";
+
+        input {
+            leaf amountOfBreadToStock {
+                type uint32;
+                description
+                  "Indicates the amount of bread to re-stock";
+            }
+        }
+    }
+
+    notification toasterOutOfBread {
+      description
+        "Indicates that the toaster has run of out bread.";
+    }  // notification toasterOutOfStock
+
+    notification toasterRestocked {
+      description
+        "Indicates that the toaster has run of out bread.";
+      leaf amountOfBread {
+        type uint32;
+        description
+          "Indicates the amount of bread that was re-stocked";
+      }
+    }  // notification toasterOutOfStock
+
+  }  // module toaster
index 08f3c73ac2646025ff8e617a4cc0a95f3afec492..8720c654c61f993f09d6503305fdc471d4065a94 100644 (file)
@@ -8,12 +8,14 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
 
 import com.google.common.base.Preconditions;
+
 import java.util.List;
 import java.util.Map;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 
 public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
 
index 68c8c6fce39eed748dcd9f9725c1c0c16c85c133..5d5721a6f870534c4e33df2942164287f4bfcfb6 100644 (file)
@@ -8,9 +8,9 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
 
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
index 1492066289d0569933e3b51a574bc03488a42df3..5d41b784f5cdaa4ff264774b05069ad6e83f3ff3 100644 (file)
@@ -16,6 +16,7 @@ import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -23,13 +24,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+
 import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
index ff1d719c57877c2df4710701d9d6f0bd65075b07..0b33b553207bf15a8b7a58c6007e0c867e296cea 100644 (file)
@@ -11,16 +11,20 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.confi
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+
 import javax.management.ObjectName;
 import javax.management.openmbean.OpenType;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader;
@@ -33,7 +37,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attrib
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 0c2b0e228e8c6763aea207c978aabdc02cd11dc1..eaab30b53be90d90c4aa8a94ff6c30cae2c6b1fb 100644 (file)
@@ -9,15 +9,18 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
 
 import com.google.common.base.Optional;
+
 import java.util.Date;
 import java.util.Map;
+
 import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
index 559de7a756f51db69d5047c5c1bd0ac6918832ea..37ad2bb22260ab45027b635d5671da8077d823b7 100644 (file)
@@ -11,16 +11,18 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.confi
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectNameAttributeReadingStrategy;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
 import javax.management.ObjectName;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
index b9518dc4d8825df28b875dbe03ccae8142fd7ca0..b1df316b1acb81010ce3a9e85d20c7b04b004f4e 100644 (file)
@@ -12,14 +12,17 @@ import com.google.common.base.Optional;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
+
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
+
 import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
index d49fe1a11629b0c5a9110b82973eac91ea25ba44..8eaaecfbb4d90904e16f7853980ea872b81fb97b 100644 (file)
@@ -13,9 +13,9 @@ import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 96a43b104d7d58a687f68744f79f6536b669f468..3cf702ed7f1b8b532d0a6834b787ee6140bc6fc7 100644 (file)
@@ -9,14 +9,15 @@
     package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 
 import com.google.common.base.Optional;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 1a7d50e5fabbc91f1359a3295a80f3f0418d6340..f443111525c8cdd154690444f9b23bca24bb4b37 100644 (file)
@@ -9,15 +9,16 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 
 import com.google.common.base.Optional;
+
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 319f539c25f02e9cbddf28b62288b5805fea8fd2..543a2c4a630d90de73dbf7aa0f837bf7dd2328f7 100644 (file)
@@ -13,12 +13,15 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
+
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
@@ -27,6 +30,7 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved;
@@ -39,7 +43,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.edi
 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
index 47220f18571a275641a7f0671cfe6da9e0e2ff1d..a3d97b1b398aacc8221b2a0ee076d6b52f3b406f 100644 (file)
@@ -11,10 +11,13 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ed
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.collect.Multimap;
+
 import java.util.Arrays;
 import java.util.Map;
+
 import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementDefinition;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved;
@@ -24,7 +27,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.Dat
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
index 48b4bbc2a825e6fd00a3d31575ffac69c0b22630..fc95046dfdbef94e3e139480cae950c7010a83f9 100644 (file)
@@ -9,14 +9,18 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.get;
 
 import com.google.common.collect.Maps;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime.InstanceRuntime;
@@ -30,7 +34,6 @@ import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceExcept
 import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -103,10 +106,7 @@ public class Get extends AbstractConfigNetconfOperation {
         xml.checkName(XmlNetconfConstants.GET);
         xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
 
-        // Filter option - unsupported
-        if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0){
-            throw new UnsupportedOperationException("Unsupported option " + XmlNetconfConstants.FILTER + " for " + XmlNetconfConstants.GET);
-        }
+        // Filter option: ignore for now, TODO only load modules specified by the filter
     }
 
     @Override
index 03e0176e32892b034b413443d3edf35cca7afb3c..fee3036214010d9dfe23453b62dee2cb70df2a17 100644 (file)
@@ -9,9 +9,12 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig;
 
 import com.google.common.base.Optional;
+import java.util.Set;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
@@ -23,16 +26,12 @@ import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceExcept
 import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
 import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.ObjectName;
-import java.util.Set;
-
 public class GetConfig extends AbstractConfigNetconfOperation {
 
     public static final String GET_CONFIG = "get-config";
@@ -65,11 +64,7 @@ public class GetConfig extends AbstractConfigNetconfOperation {
         logger.debug("Setting source datastore to '{}'", sourceParsed);
         Datastore sourceDatastore = Datastore.valueOf(sourceParsed);
 
-        // Filter option - unsupported
-        if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0){
-            throw new UnsupportedOperationException("Unsupported option " + XmlNetconfConstants.FILTER + " for "
-                    + GET_CONFIG);
-        }
+        // Filter option: ignore for now, TODO only load modules specified by the filter
 
         return sourceDatastore;
 
index 98eb17699973cc1e2448c5072421a0e29b205280..21021fec55661f69cd2c1e19325f0dd651e07193 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ru
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
@@ -18,6 +19,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.VoidAttribute;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.AttributeMappingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectMapper;
@@ -31,7 +33,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStore
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,6 +41,7 @@ import org.w3c.dom.Element;
 
 import javax.management.ObjectName;
 import javax.management.openmbean.OpenType;
+
 import java.util.Map;
 
 public class RuntimeRpc extends AbstractConfigNetconfOperation {
index 5cf7f30abcaa5cf356a2faf89635c0cb1ee06f63..7fd8928928feb8814b0eb003c61e2c51152beef5 100644 (file)
@@ -11,11 +11,13 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ru
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.ModuleRpcs;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 
 import javax.management.ObjectName;
+
 import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Matcher;
index 41301543a33f54754f0ccfc7bda24f2a9b818f74..e41b174b664740c685faa041d64c208630bf21c2 100644 (file)
@@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -42,10 +43,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
 import javax.xml.parsers.ParserConfigurationException;
+
 import org.custommonkey.xmlunit.AbstractNodeTester;
 import org.custommonkey.xmlunit.NodeTest;
 import org.custommonkey.xmlunit.NodeTestException;
@@ -80,6 +83,7 @@ import org.opendaylight.controller.config.yang.test.impl.Peers;
 import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.DiscardChanges;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
@@ -96,7 +100,6 @@ import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
index d393121a269700aeb1adda313eedff43b613a806..b5c5dd35442704253a4b1e906ab674e0b4a19b71 100644 (file)
@@ -11,9 +11,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 import org.junit.Test;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Element;
 
index 957db50c61a8b7ca076fc26fcc2c9886251f73bb..8d85a35bc79ad3f77eb516c14cb23b2003974c13 100644 (file)
@@ -25,6 +25,7 @@ import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.mapping.api.Capability;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
@@ -33,7 +34,6 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 import org.opendaylight.controller.netconf.util.NetconfUtil;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 061fbd7c8c7a0179d4d6147d40733a251875bcb9..815acec5e789cd7d491e5783886492713141405b 100644 (file)
@@ -48,6 +48,7 @@
           <instructions>
             <Private-Package></Private-Package>
             <Import-Package>javax.management,
+                            javax.xml.parsers,
                             org.opendaylight.controller.config.api,
                             org.opendaylight.controller.config.api.jmx,
                             org.opendaylight.protocol.framework,
@@ -62,6 +63,7 @@
                             com.google.common.base,</Import-Package>
             <Export-Package>org.opendaylight.controller.netconf.api,
                             org.opendaylight.controller.netconf.api.jmx,
+                            org.opendaylight.controller.netconf.api.xml,
                             org.opendaylight.controller.netconf.api.monitoring,</Export-Package>
           </instructions>
         </configuration>
index 1ecbc55b2a02ac7af0757e777d960956cfddc0a0..0c365b9d30ebcb5463440404b0c9d10a3a015d5c 100644 (file)
@@ -8,12 +8,30 @@
 
 package org.opendaylight.controller.netconf.api;
 
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.api.ValidationException;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_INFO;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_MESSAGE;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_SEVERITY;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_TAG;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.ERROR_TYPE;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_ERROR;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_REPLY_KEY;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
 
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * Checked exception to communicate an error that needs to be sent to the
@@ -23,7 +41,17 @@ public class NetconfDocumentedException extends Exception {
 
     private static final long serialVersionUID = 1L;
 
+    private final static Logger LOG = LoggerFactory.getLogger( NetconfDocumentedException.class );
 
+    private static final DocumentBuilderFactory BUILDER_FACTORY;
+
+    static {
+        BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
+        BUILDER_FACTORY.setNamespaceAware(true);
+        BUILDER_FACTORY.setCoalescing(true);
+        BUILDER_FACTORY.setIgnoringElementContentWhitespace(true);
+        BUILDER_FACTORY.setIgnoringComments(true);
+    }
 
     public enum ErrorType {
         transport, rpc, protocol, application;
@@ -31,12 +59,37 @@ public class NetconfDocumentedException extends Exception {
         public String getTagValue() {
             return name();
         }
+
+        public static ErrorType from( String text ) {
+            try {
+                return valueOf( text );
+            }
+            catch( Exception e ) {
+                return application;
+            }
+        }
     }
 
     public enum ErrorTag {
-        missing_attribute("missing-attribute"), unknown_element("unknown-element"), operation_not_supported(
-                "operation-not-supported"), bad_attribute("bad-attribute"), data_missing("data-missing"), operation_failed(
-                "operation-failed"), invalid_value("invalid-value"), malformed_message("malformed-message");
+        access_denied("access-denied"),
+        bad_attribute("bad-attribute"),
+        bad_element("bad-element"),
+        data_exists("data-exists"),
+        data_missing("data-missing"),
+        in_use("in-use"),
+        invalid_value("invalid-value"),
+        lock_denied("lock-denied"),
+        malformed_message("malformed-message"),
+        missing_attribute("missing-attribute"),
+        missing_element("missing-element"),
+        operation_failed("operation-failed"),
+        operation_not_supported("operation-not-supported"),
+        resource_denied("resource-denied"),
+        rollback_failed("rollback-failed"),
+        too_big("too-big"),
+        unknown_attribute("unknown-attribute"),
+        unknown_element("unknown-element"),
+        unknown_namespace("unknown-namespace");
 
         private final String tagValue;
 
@@ -47,6 +100,17 @@ public class NetconfDocumentedException extends Exception {
         public String getTagValue() {
             return this.tagValue;
         }
+
+        public static ErrorTag from( String text ) {
+            for( ErrorTag e: values() )
+            {
+                if( e.getTagValue().equals( text ) ) {
+                    return e;
+                }
+            }
+
+            return operation_failed;
+        }
     }
 
     public enum ErrorSeverity {
@@ -55,6 +119,15 @@ public class NetconfDocumentedException extends Exception {
         public String getTagValue() {
             return name();
         }
+
+        public static ErrorSeverity from( String text ) {
+            try {
+                return valueOf( text );
+            }
+            catch( Exception e ) {
+                return error;
+            }
+        }
     }
 
     private final ErrorType errorType;
@@ -118,6 +191,64 @@ public class NetconfDocumentedException extends Exception {
                 ErrorSeverity.error, errorInfo);
     }
 
+    public static NetconfDocumentedException fromXMLDocument( Document fromDoc ) {
+
+        ErrorType errorType = ErrorType.application;
+        ErrorTag errorTag = ErrorTag.operation_failed;
+        ErrorSeverity errorSeverity = ErrorSeverity.error;
+        Map<String, String> errorInfo = null;
+        String errorMessage = "";
+
+        Node rpcReply = fromDoc.getDocumentElement();
+
+        // FIXME: BUG? - we only handle one rpc-error.
+
+        NodeList replyChildren = rpcReply.getChildNodes();
+        for( int i = 0; i < replyChildren.getLength(); i++ ) {
+            Node replyChild = replyChildren.item( i );
+            if( RPC_ERROR.equals( replyChild.getNodeName() ) )
+            {
+                NodeList rpcErrorChildren = replyChild.getChildNodes();
+                for( int j = 0; j < rpcErrorChildren.getLength(); j++ )
+                {
+                    Node rpcErrorChild = rpcErrorChildren.item( j );
+                    if( ERROR_TYPE.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorType = ErrorType.from( rpcErrorChild.getTextContent() );
+                    }
+                    else if( ERROR_TAG.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorTag = ErrorTag.from( rpcErrorChild.getTextContent() );
+                    }
+                    else if( ERROR_SEVERITY.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorSeverity = ErrorSeverity.from( rpcErrorChild.getTextContent() );
+                    }
+                    else if( ERROR_MESSAGE.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorMessage = rpcErrorChild.getTextContent();
+                    }
+                    else if( ERROR_INFO.equals( rpcErrorChild.getNodeName() ) ) {
+                        errorInfo = parseErrorInfo( rpcErrorChild );
+                    }
+                }
+
+                break;
+            }
+        }
+
+        return new NetconfDocumentedException( errorMessage, errorType, errorTag, errorSeverity, errorInfo );
+    }
+
+    private static Map<String, String> parseErrorInfo( Node node ) {
+        Map<String, String> infoMap = new HashMap<>();
+        NodeList children = node.getChildNodes();
+        for( int i = 0; i < children.getLength(); i++ ) {
+            Node child = children.item( i );
+            if( child.getNodeType() == Node.ELEMENT_NODE ) {
+                infoMap.put( child.getNodeName(), child.getTextContent() );
+            }
+        }
+
+        return infoMap;
+    }
+
     public ErrorType getErrorType() {
         return this.errorType;
     }
@@ -134,6 +265,53 @@ public class NetconfDocumentedException extends Exception {
         return this.errorInfo;
     }
 
+    public Document toXMLDocument() {
+        Document doc = null;
+        try {
+            doc = BUILDER_FACTORY.newDocumentBuilder().newDocument();
+
+            Node rpcReply = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, RPC_REPLY_KEY );
+            doc.appendChild( rpcReply );
+
+            Node rpcError = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, RPC_ERROR );
+            rpcReply.appendChild( rpcError );
+
+            rpcError.appendChild( createTextNode( doc, ERROR_TYPE, getErrorType().getTagValue() ) );
+            rpcError.appendChild( createTextNode( doc, ERROR_TAG, getErrorTag().getTagValue() ) );
+            rpcError.appendChild( createTextNode( doc, ERROR_SEVERITY, getErrorSeverity().getTagValue() ) );
+            rpcError.appendChild( createTextNode( doc, ERROR_MESSAGE, getLocalizedMessage() ) );
+
+            Map<String, String> errorInfoMap = getErrorInfo();
+            if( errorInfoMap != null && !errorInfoMap.isEmpty() ) {
+                /*
+                 * <error-info>
+                 *   <bad-attribute>message-id</bad-attribute>
+                 *   <bad-element>rpc</bad-element>
+                 * </error-info>
+                 */
+
+                Node errorInfoNode = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, ERROR_INFO );
+                errorInfoNode.setPrefix( rpcReply.getPrefix() );
+                rpcError.appendChild( errorInfoNode );
+
+                for ( Entry<String, String> entry : errorInfoMap.entrySet() ) {
+                    errorInfoNode.appendChild( createTextNode( doc, entry.getKey(), entry.getValue() ) );
+                }
+            }
+        }
+        catch( ParserConfigurationException e ) {
+            LOG.error( "Error outputting to XML document", e ); // this shouldn't happen
+        }
+
+        return doc;
+    }
+
+    private Node createTextNode( Document doc, String tag, String textContent ) {
+        Node node = doc.createElementNS( URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, tag );
+        node.setTextContent( textContent );
+        return node;
+    }
+
     @Override
     public String toString() {
         return "NetconfDocumentedException{" + "message=" + getMessage() + ", errorType=" + this.errorType
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.netconf.util.xml;
+package org.opendaylight.controller.netconf.api.xml;
 
 public final class XmlNetconfConstants {
 
@@ -34,6 +34,13 @@ public final class XmlNetconfConstants {
     public static final String RPC_KEY = "rpc";
     public static final String RPC_REPLY_KEY = "rpc-reply";
     public static final String RPC_ERROR = "rpc-error";
+    public static final String ERROR_TYPE = "error-type";
+    public static final String ERROR_TAG = "error-tag";
+    public static final String ERROR_SEVERITY = "error-severity";
+    public static final String ERROR_APP_TAG = "error-app-tag";
+    public static final String ERROR_PATH = "error-path";
+    public static final String ERROR_MESSAGE = "error-message";
+    public static final String ERROR_INFO = "error-info";
     public static final String NAME_KEY = "name";
     public static final String NOTIFICATION_ELEMENT_NAME = "notification";
 
@@ -56,4 +63,5 @@ public final class XmlNetconfConstants {
     // TODO where to store namespace of config ?
     public static final String URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG = "urn:opendaylight:params:xml:ns:yang:controller:config";
     public static final String GET = "get";
+    public static final String GET_CONFIG = "get-config";
 }
diff --git a/opendaylight/netconf/netconf-api/src/test/java/org/opendaylight/controller/netconf/api/NetconfDocumentedExceptionTest.java b/opendaylight/netconf/netconf-api/src/test/java/org/opendaylight/controller/netconf/api/NetconfDocumentedExceptionTest.java
new file mode 100644 (file)
index 0000000..cdf8b91
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import com.google.common.collect.ImmutableMap;
+
+
+/**
+ * Unit tests for NetconfDocumentedException.
+ *
+ * @author Thomas Pantelis
+ */
+public class NetconfDocumentedExceptionTest {
+
+    private XPath xpath;
+
+    @Before
+    public void setUp() throws Exception {
+        XPathFactory xPathfactory = XPathFactory.newInstance();
+        xpath = xPathfactory.newXPath();
+        xpath.setNamespaceContext( new NamespaceContext() {
+            @Override
+            public Iterator<?> getPrefixes( String namespaceURI ) {
+                return Collections.singletonList( "netconf" ).iterator();
+            }
+
+            @Override
+            public String getPrefix( String namespaceURI ) {
+                return "netconf";
+            }
+
+            @Override
+            public String getNamespaceURI( String prefix ) {
+                return XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
+            }
+        } );
+    }
+
+    @Test
+    public void testToAndFromXMLDocument() throws XPathExpressionException {
+        String errorMessage = "mock error message";
+        NetconfDocumentedException ex = new NetconfDocumentedException( errorMessage, null,
+                                                                        ErrorType.protocol,
+                                                                        ErrorTag.data_exists,
+                                                                        ErrorSeverity.warning,
+                                                                        ImmutableMap.of( "foo", "bar" ) );
+
+        Document doc = ex.toXMLDocument();
+        assertNotNull( "Document is null", doc );
+
+        Node rootNode = doc.getDocumentElement();
+
+        assertEquals( "getNamespaceURI", "urn:ietf:params:xml:ns:netconf:base:1.0", rootNode.getNamespaceURI() );
+        assertEquals( "getLocalName", "rpc-reply", rootNode.getLocalName() );
+
+        Node rpcErrorNode = getNode( "/netconf:rpc-reply/netconf:rpc-error", rootNode );
+        assertNotNull( "rpc-error not found", rpcErrorNode );
+
+        Node errorTypeNode = getNode( "netconf:error-type", rpcErrorNode );
+        assertNotNull( "error-type not found", errorTypeNode );
+        assertEquals( "error-type", ErrorType.protocol.getTagValue(),
+                      errorTypeNode.getTextContent() );
+
+        Node errorTagNode = getNode( "netconf:error-tag", rpcErrorNode );
+        assertNotNull( "error-tag not found", errorTagNode );
+        assertEquals( "error-tag", ErrorTag.data_exists.getTagValue(),
+                      errorTagNode.getTextContent() );
+
+        Node errorSeverityNode = getNode( "netconf:error-severity", rpcErrorNode );
+        assertNotNull( "error-severity not found", errorSeverityNode );
+        assertEquals( "error-severity", ErrorSeverity.warning.getTagValue(),
+                      errorSeverityNode.getTextContent() );
+
+        Node errorInfoNode = getNode( "netconf:error-info/netconf:foo", rpcErrorNode );
+        assertNotNull( "foo not found", errorInfoNode );
+        assertEquals( "foo", "bar", errorInfoNode.getTextContent() );
+
+        Node errorMsgNode = getNode( "netconf:error-message", rpcErrorNode );
+        assertNotNull( "error-message not found", errorMsgNode );
+        assertEquals( "error-message", errorMessage, errorMsgNode.getTextContent() );
+
+        // Test fromXMLDocument
+
+        ex = NetconfDocumentedException.fromXMLDocument( doc );
+
+        assertNotNull( "NetconfDocumentedException is null", ex );
+        assertEquals( "getErrorSeverity", ErrorSeverity.warning, ex.getErrorSeverity() );
+        assertEquals( "getErrorTag", ErrorTag.data_exists, ex.getErrorTag() );
+        assertEquals( "getErrorType", ErrorType.protocol, ex.getErrorType() );
+        assertEquals( "getLocalizedMessage", errorMessage, ex.getLocalizedMessage() );
+        assertEquals( "getErrorInfo", ImmutableMap.of( "foo", "bar" ), ex.getErrorInfo() );
+    }
+
+    @SuppressWarnings("unchecked")
+    <T> T getNode( String xpathExp, Node node ) throws XPathExpressionException {
+        return (T)xpath.compile( xpathExp ).evaluate( node, XPathConstants.NODE );
+    }
+}
+
index eaa3589e66d32c6e448c12ee6b04e60ca457dfdd..004a22f6948c570e96fc880ea764b366c8cbfd94 100644 (file)
@@ -19,7 +19,7 @@ import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessage
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public final class NetconfClientSession extends AbstractNetconfSession<NetconfClientSession, NetconfClientSessionListener> {
+public class NetconfClientSession extends AbstractNetconfSession<NetconfClientSession, NetconfClientSessionListener> {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class);
     private final Collection<String> capabilities;
index bb6ea61a25b5fa51e56af04af1b01f533205df18..971ea39ade5b6fb57d07a041f999ec18890528df 100644 (file)
@@ -15,19 +15,22 @@ import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.util.Timer;
 import io.netty.util.concurrent.Promise;
+
 import java.util.Collection;
+
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpression;
+
 import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
 import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSessionNegotiator;
 import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
 import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 4c993acf58f3e8640d3aea09468ea0283134a903..3b1de348ff86858884d27a6436ddc0c0d62692fb 100644 (file)
@@ -11,16 +11,18 @@ package org.opendaylight.controller.netconf.client;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Sets;
+
 import io.netty.channel.Channel;
 import io.netty.util.Timer;
 import io.netty.util.concurrent.Promise;
+
 import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 import org.opendaylight.protocol.framework.SessionNegotiator;
 import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
index 75be1f8fe01647beeabbcb1101bd5265c7813578..4f2f65c1a00732137229fba7e1416d9c1db70904 100644 (file)
@@ -11,16 +11,17 @@ package org.opendaylight.controller.netconf.impl;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.api.NetconfSessionListener;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
 import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -98,7 +99,7 @@ public class NetconfServerSessionListener implements NetconfSessionListener<Netc
             session.onIncommingRpcFail();
             throw new IllegalStateException("Unable to process incoming message " + netconfMessage, e);
         } catch (NetconfDocumentedException e) {
-            logger.trace("Error occured while processing mesage {}",e);
+            logger.trace("Error occurred while processing message",e);
             session.onOutgoingRpcError();
             session.onIncommingRpcFail();
             SendErrorExceptionUtil.sendErrorMessage(session, e, netconfMessage);
@@ -111,6 +112,8 @@ public class NetconfServerSessionListener implements NetconfSessionListener<Netc
         logger.info("Session {} closed successfully", session.getSessionId());
     }
 
+
+
     private NetconfMessage processDocument(final NetconfMessage netconfMessage, NetconfServerSession session)
             throws NetconfDocumentedException {
 
@@ -123,6 +126,8 @@ public class NetconfServerSessionListener implements NetconfSessionListener<Netc
 
             Document rpcReply = operationRouter.onNetconfMessage(incomingDocument, session);
 
+            rpcReply = SubtreeFilter.applySubtreeFilter(incomingDocument, rpcReply);
+
             session.onIncommingRpcSuccess();
 
             responseDocument.appendChild(responseDocument.importNode(rpcReply.getDocumentElement(), true));
index d5a34d11b244681b1540ff95bae22b26ba607670..487ffd6e5dc2d8f5e7dbd13db1402b3d7e0559a7 100644 (file)
@@ -12,16 +12,17 @@ import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationPr
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableSet;
+
 import java.util.Set;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 import org.opendaylight.protocol.framework.SessionNegotiator;
 import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
@@ -31,6 +32,7 @@ import com.google.common.collect.Sets;
 import io.netty.channel.Channel;
 import io.netty.util.Timer;
 import io.netty.util.concurrent.Promise;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SubtreeFilter.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SubtreeFilter.java
new file mode 100644 (file)
index 0000000..6e81584
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.impl;
+
+import com.google.common.base.Optional;
+import java.io.IOException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation.OperationNameAndNamespace;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+/**
+ * See <a href="http://tools.ietf.org/html/rfc6241#section-6">rfc6241</a> for details.
+ */
+public class SubtreeFilter {
+    private static final Logger logger = LoggerFactory.getLogger(SubtreeFilter.class);
+
+    static Document applySubtreeFilter(Document requestDocument, Document rpcReply) throws NetconfDocumentedException {
+        // FIXME: rpcReply document must be reread otherwise some nodes do not inherit namespaces. (services/service)
+        try {
+            rpcReply = XmlUtil.readXmlToDocument(XmlUtil.toString(rpcReply, true));
+        } catch (SAXException | IOException e) {
+            logger.error("Cannot transform document", e);
+            throw new NetconfDocumentedException("Cannot transform document");
+        }
+
+        OperationNameAndNamespace operationNameAndNamespace = new OperationNameAndNamespace(requestDocument);
+        if (XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0.equals(operationNameAndNamespace.getNamespace()) &&
+                XmlNetconfConstants.GET.equals(operationNameAndNamespace.getOperationName()) ||
+                XmlNetconfConstants.GET_CONFIG.equals(operationNameAndNamespace.getOperationName())) {
+            // process subtree filtering here, in case registered netconf operations do
+            // not implement filtering.
+            Optional<XmlElement> maybeFilter = operationNameAndNamespace.getOperationElement().getOnlyChildElementOptionally(
+                    XmlNetconfConstants.FILTER, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+            if (maybeFilter.isPresent() && (
+                    "subtree".equals(maybeFilter.get().getAttribute("type"))||
+                            "subtree".equals(maybeFilter.get().getAttribute("type", XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0))
+            )) {
+
+
+                // do
+                return filtered(maybeFilter.get(), rpcReply);
+            }
+        }
+        return rpcReply; // return identical document
+    }
+
+    private static Document filtered(XmlElement filter, Document originalReplyDocument) throws NetconfDocumentedException {
+        Document result = XmlUtil.newDocument();
+        // even if filter is empty, copy /rpc/data
+        Element rpcReply = originalReplyDocument.getDocumentElement();
+        Node rpcReplyDst = result.importNode(rpcReply, false);
+        result.appendChild(rpcReplyDst);
+        XmlElement dataSrc = XmlElement.fromDomElement(rpcReply).getOnlyChildElement("data", XmlNetconfConstants.RFC4741_TARGET_NAMESPACE);
+        Element dataDst = (Element) result.importNode(dataSrc.getDomElement(), false);
+        rpcReplyDst.appendChild(dataDst);
+        addSubtree(filter, dataSrc, XmlElement.fromDomElement(dataDst));
+
+        return result;
+    }
+
+    private static void addSubtree(XmlElement filter, XmlElement src, XmlElement dst) {
+        for (XmlElement srcChild : src.getChildElements()) {
+            for (XmlElement filterChild : filter.getChildElements()) {
+                addSubtree2(filterChild, srcChild, dst);
+            }
+        }
+    }
+
+    private static MatchingResult addSubtree2(XmlElement filter, XmlElement src, XmlElement dstParent) {
+        Document document = dstParent.getDomElement().getOwnerDocument();
+        MatchingResult matches = matches(src, filter);
+        if (matches != MatchingResult.NO_MATCH && matches != MatchingResult.CONTENT_MISMATCH) {
+            // copy srcChild to dst
+            boolean filterHasChildren = filter.getChildElements().isEmpty() == false;
+            // copy to depth if this is leaf of filter tree
+            Element copied = (Element) document.importNode(src.getDomElement(), filterHasChildren == false);
+            boolean shouldAppend = filterHasChildren == false;
+            if (filterHasChildren) { // this implies TAG_MATCH
+                // do the same recursively
+                int numberOfTextMatchingChildren = 0;
+                for (XmlElement srcChild : src.getChildElements()) {
+                    for (XmlElement filterChild : filter.getChildElements()) {
+                        MatchingResult childMatch = addSubtree2(filterChild, srcChild, XmlElement.fromDomElement(copied));
+                        if (childMatch == MatchingResult.CONTENT_MISMATCH) {
+                            return MatchingResult.NO_MATCH;
+                        }
+                        if (childMatch == MatchingResult.CONTENT_MATCH) {
+                            numberOfTextMatchingChildren++;
+                        }
+                        shouldAppend |= childMatch != MatchingResult.NO_MATCH;
+                    }
+                }
+                // if only text matching child filters are specified..
+                if (numberOfTextMatchingChildren == filter.getChildElements().size()) {
+                    // force all children to be added (to depth). This is done by copying parent node to depth.
+                    // implies shouldAppend == true
+                    copied = (Element) document.importNode(src.getDomElement(), true);
+                }
+            }
+            if (shouldAppend) {
+                dstParent.getDomElement().appendChild(copied);
+            }
+        }
+        return matches;
+    }
+
+    /**
+     * Shallow compare src node to filter: tag name and namespace must match.
+     * If filter node has no children and has text content, it also must match.
+     */
+    private static MatchingResult matches(XmlElement src, XmlElement filter) {
+        boolean tagMatch = src.getName().equals(filter.getName()) &&
+                src.getNamespaceOptionally().equals(filter.getNamespaceOptionally());
+        MatchingResult result = null;
+        if (tagMatch) {
+            // match text content
+            Optional<String> maybeText = filter.getOnlyTextContentOptionally();
+            if (maybeText.isPresent()) {
+                if (maybeText.equals(src.getOnlyTextContentOptionally())) {
+                    result = MatchingResult.CONTENT_MATCH;
+                } else {
+                    result = MatchingResult.CONTENT_MISMATCH;
+                }
+            }
+            // match attributes, combination of content and tag is not supported
+            if (result == null) {
+                for (Attr attr : filter.getAttributes().values()) {
+                    // ignore namespace declarations
+                    if (XmlUtil.XMLNS_URI.equals(attr.getNamespaceURI()) == false ) {
+                        // find attr with matching localName(),  namespaceURI(),  == value() in src
+                        String found = src.getAttribute(attr.getLocalName(), attr.getNamespaceURI());
+                        if (attr.getValue().equals(found) && result != MatchingResult.NO_MATCH) {
+                            result = MatchingResult.TAG_MATCH;
+                        } else {
+                            result = MatchingResult.NO_MATCH;
+                        }
+                    }
+                }
+            }
+            if (result == null) {
+                result = MatchingResult.TAG_MATCH;
+            }
+        }
+        if (result == null) {
+            result = MatchingResult.NO_MATCH;
+        }
+        logger.debug("Matching {} to {} resulted in {}", src, filter, tagMatch);
+        return result;
+    }
+
+    enum MatchingResult {
+        NO_MATCH, TAG_MATCH, CONTENT_MATCH, CONTENT_MISMATCH
+    }
+}
index f31233987e97531a563fca3f186fee480e6b6616..b7a98bae83acae9a1ee0f525a015db251c998f3e 100644 (file)
@@ -9,9 +9,9 @@
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
index d4545430b47834ae8604737a50762056fd712526..67b782c7c1d7666a32f78fe08f0ff77d5dd9f17e 100644 (file)
@@ -9,7 +9,9 @@
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
 import com.google.common.base.Preconditions;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
@@ -17,7 +19,6 @@ import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index beceb8d008cb6e6b61662cf16f6ea32bd31981ed..6db74eaba2ec0aba6efb421b40e12e735709edde 100644 (file)
@@ -10,12 +10,13 @@ package org.opendaylight.controller.netconf.impl.mapping.operations;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index b9b30a5eaaa2b52b4967e102e373a578cf08b2ea..cccb1a3ac362e35c6f0efcd5836b3c5a51e1a320 100644 (file)
@@ -11,12 +11,12 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;\r
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;\r
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;\r
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.api.NetconfMessage;\r
 import org.opendaylight.controller.netconf.impl.NetconfServerSession;\r
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;\r
 import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;\r
 import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
index 22caeff071c44939f309d84c8187f2034172bd04..2a24ae32fa0cad9bef292cd53cc8718424692b7c 100644 (file)
@@ -8,10 +8,10 @@
 package org.opendaylight.controller.netconf.impl.mapping.operations;\r
 \r
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.impl.NetconfServerSession;\r
 import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;\r
 import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
index ea2bb9c34e4801f5c66b33ef108110602ba5c60b..c5281d01f841263d5f1258975ee85764565a111d 100644 (file)
@@ -18,11 +18,13 @@ import static org.mockito.Mockito.mock;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
+
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.concurrent.GlobalEventExecutor;
+
 import java.io.DataOutputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -40,6 +42,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicLong;
+
 import org.apache.commons.io.IOUtils;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -50,6 +53,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
@@ -68,7 +72,6 @@ import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExi
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
 import org.slf4j.Logger;
diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/SubtreeFilterTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/SubtreeFilterTest.java
new file mode 100644 (file)
index 0000000..b118343
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.impl;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+@RunWith(value = Parameterized.class)
+public class SubtreeFilterTest {
+    private static final Logger logger = LoggerFactory.getLogger(SubtreeFilterTest.class);
+
+    private final int directoryIndex;
+
+    @Parameters
+    public static Collection<Object[]> data() {
+        List<Object[]> result = new ArrayList<>();
+        for (int i = 0; i <= 8; i++) {
+            result.add(new Object[]{i});
+        }
+        return result;
+    }
+
+    public SubtreeFilterTest(int directoryIndex) {
+        this.directoryIndex = directoryIndex;
+    }
+
+    @Before
+    public void setUp(){
+        XMLUnit.setIgnoreWhitespace(true);
+    }
+
+    @Test
+    public void test() throws Exception {
+        Document requestDocument = getDocument("request.xml");
+        Document preFilterDocument = getDocument("pre-filter.xml");
+        Document postFilterDocument = getDocument("post-filter.xml");
+        Document actualPostFilterDocument = SubtreeFilter.applySubtreeFilter(requestDocument, preFilterDocument);
+        logger.info("Actual document: {}", XmlUtil.toString(actualPostFilterDocument));
+        Diff diff = XMLUnit.compareXML(postFilterDocument, actualPostFilterDocument);
+        assertTrue(diff.toString(), diff.similar());
+
+    }
+
+    public Document getDocument(String fileName) throws SAXException, IOException {
+        return XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/subtree/" + directoryIndex + "/" +
+                fileName));
+    }
+}
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/getConfig_reply_unfiltered.xml b/opendaylight/netconf/netconf-impl/src/test/resources/getConfig_reply_unfiltered.xml
new file mode 100644 (file)
index 0000000..3c2765a
--- /dev/null
@@ -0,0 +1,439 @@
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-2">
+  <data>
+    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+          prefix:toaster-provider-impl
+        </type>
+        <name>toaster-provider-impl</name>
+        <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+            prefix:binding-notification-service
+          </type>
+          <name>binding-notification-broker</name>
+        </notification-service>
+        <rpc-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+            prefix:binding-rpc-registry
+          </type>
+          <name>binding-rpc-broker</name>
+        </rpc-registry>
+        <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+            prefix:binding-data-broker
+          </type>
+          <name>binding-data-broker</name>
+        </data-broker>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          prefix:sal-netconf-connector
+        </type>
+        <name>controller-config</name>
+        <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">1830</port>
+        <connection-timeout-millis xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          20000
+        </connection-timeout-millis>
+        <between-attempts-timeout-millis
+                xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">2000
+        </between-attempts-timeout-millis>
+        <sleep-factor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">1.5</sleep-factor>
+        <password xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">admin</password>
+        <dom-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+            prefix:dom-broker-osgi-registry
+          </type>
+          <name>dom-broker</name>
+        </dom-registry>
+        <client-dispatcher xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">
+            prefix:netconf-client-dispatcher
+          </type>
+          <name>global-netconf-dispatcher</name>
+        </client-dispatcher>
+        <username xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">admin</username>
+        <address xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">127.0.0.1</address>
+        <processing-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>
+          <name>global-netconf-processing-executor</name>
+        </processing-executor>
+        <tcp-only xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">false</tcp-only>
+        <binding-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+            prefix:binding-broker-osgi-registry
+          </type>
+          <name>binding-osgi-broker</name>
+        </binding-registry>
+        <max-connection-attempts xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">0
+        </max-connection-attempts>
+        <event-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>
+          <name>global-event-executor</name>
+        </event-executor>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+          prefix:netconf-client-dispatcher
+        </type>
+        <name>global-netconf-dispatcher</name>
+        <worker-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+          <name>global-worker-group</name>
+        </worker-thread-group>
+        <timer xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-timer</type>
+          <name>global-timer</name>
+        </timer>
+        <boss-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+          <name>global-boss-group</name>
+        </boss-thread-group>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:logback:config">prefix:logback</type>
+        <name>singleton</name>
+        <console-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <threshold-filter>ERROR</threshold-filter>
+          <name>STDOUT</name>
+          <encoder-pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</encoder-pattern>
+        </console-appenders>
+        <file-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <append>true</append>
+          <file-name>logs/audit.log</file-name>
+          <name>audit-file</name>
+          <encoder-pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} %msg %n</encoder-pattern>
+        </file-appenders>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>WARN</level>
+          <logger-name>org.opendaylight.controller.logging.bridge</logger-name>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>INFO</level>
+          <logger-name>audit</logger-name>
+          <appenders>audit-file</appenders>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>ERROR</level>
+          <logger-name>ROOT</logger-name>
+          <appenders>STDOUT</appenders>
+          <appenders>opendaylight.log</appenders>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>INFO</level>
+          <logger-name>org.opendaylight</logger-name>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>INFO</level>
+          <logger-name>org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort</logger-name>
+          <appenders>opendaylight.log</appenders>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>TRACE</level>
+          <logger-name>org.opendaylight.controller.netconf</logger-name>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>WARN</level>
+          <logger-name>io.netty</logger-name>
+        </loggers>
+        <rolling-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <append>true</append>
+          <max-file-size>10MB</max-file-size>
+          <file-name>logs/opendaylight.log</file-name>
+          <name>opendaylight.log</name>
+          <file-name-pattern>logs/opendaylight.%d.log.zip</file-name-pattern>
+          <encoder-pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n</encoder-pattern>
+          <clean-history-on-start>false</clean-history-on-start>
+          <max-history>1</max-history>
+          <rolling-policy-type>TimeBasedRollingPolicy</rolling-policy-type>
+        </rolling-appenders>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl">prefix:shutdown</type>
+        <name>shutdown</name>
+        <secret xmlns="urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl"/>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty:timer">
+          prefix:netty-hashed-wheel-timer
+        </type>
+        <name>global-timer</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">
+          prefix:netty-threadgroup-fixed
+        </type>
+        <name>global-boss-group</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">
+          prefix:netty-threadgroup-fixed
+        </type>
+        <name>global-worker-group</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+          prefix:schema-service-singleton
+        </type>
+        <name>yang-schema-service</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl
+        </type>
+        <name>inmemory-dom-broker</name>
+        <async-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-async-data-broker
+          </type>
+          <name>inmemory-data-broker</name>
+        </async-data-broker>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+          prefix:dom-inmemory-data-broker
+        </type>
+        <name>inmemory-data-broker</name>
+        <schema-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:schema-service</type>
+          <name>yang-schema-service</name>
+        </schema-service>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">
+          prefix:threadpool-flexible
+        </type>
+        <name>global-netconf-processing-executor</name>
+        <threadFactory xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
+          <name>global-netconf-processing-executor-threadfactory</name>
+        </threadFactory>
+        <minThreadCount xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">1
+        </minThreadCount>
+        <max-thread-count xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">4
+        </max-thread-count>
+        <keepAliveMillis xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">600000
+        </keepAliveMillis>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor">
+          prefix:netty-global-event-executor
+        </type>
+        <name>singleton</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          prefix:binding-broker-impl
+        </type>
+        <name>binding-broker-impl</name>
+        <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+            prefix:binding-notification-service
+          </type>
+          <name>binding-notification-broker</name>
+        </notification-service>
+        <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+            prefix:binding-data-broker
+          </type>
+          <name>binding-data-broker</name>
+        </data-broker>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          prefix:runtime-generated-mapping
+        </type>
+        <name>runtime-mapping-singleton</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          prefix:binding-notification-broker
+        </type>
+        <name>binding-notification-broker</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          prefix:binding-data-compatible-broker
+        </type>
+        <name>inmemory-binding-data-broker</name>
+        <dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+            prefix:dom-broker-osgi-registry
+          </type>
+          <name>dom-broker</name>
+        </dom-async-broker>
+        <binding-mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+            prefix:binding-dom-mapping-service
+          </type>
+          <name>runtime-mapping-singleton</name>
+        </binding-mapping-service>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">
+          prefix:threadfactory-naming
+        </type>
+        <name>global-netconf-processing-executor-threadfactory</name>
+        <name-prefix xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">
+          remote-connector-processing-executor
+        </name-prefix>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+          prefix:kitchen-service-impl
+        </type>
+        <name>kitchen-service-impl</name>
+        <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+            prefix:binding-notification-service
+          </type>
+          <name>binding-notification-broker</name>
+        </notification-service>
+        <rpc-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+            prefix:binding-rpc-registry
+          </type>
+          <name>binding-rpc-broker</name>
+        </rpc-registry>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
+          prefix:remote-zeromq-rpc-server
+        </type>
+        <name>remoter</name>
+        <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
+        <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+            prefix:dom-broker-osgi-registry
+          </type>
+          <name>dom-broker</name>
+        </dom-broker>
+      </module>
+    </modules>
+    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:schema-service</type>
+        <instance>
+          <name>yang-schema-service</name>
+          <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry
+        </type>
+        <instance>
+          <name>dom-broker</name>
+          <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-async-data-broker
+        </type>
+        <instance>
+          <name>inmemory-data-broker</name>
+          <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>
+        <instance>
+          <name>global-netconf-processing-executor</name>
+          <provider>/modules/module[type='threadpool-flexible'][name='global-netconf-processing-executor']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
+        <instance>
+          <name>global-netconf-processing-executor-threadfactory</name>
+          <provider>
+            /modules/module[type='threadfactory-naming'][name='global-netconf-processing-executor-threadfactory']
+          </provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          prefix:binding-dom-mapping-service
+        </type>
+        <instance>
+          <name>runtime-mapping-singleton</name>
+          <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-timer</type>
+        <instance>
+          <name>global-timer</name>
+          <provider>/modules/module[type='netty-hashed-wheel-timer'][name='global-timer']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+        <instance>
+          <name>global-boss-group</name>
+          <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-boss-group']</provider>
+        </instance>
+        <instance>
+          <name>global-worker-group</name>
+          <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-worker-group']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>
+        <instance>
+          <name>global-event-executor</name>
+          <provider>/modules/module[type='netty-global-event-executor'][name='singleton']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-rpc-registry
+        </type>
+        <instance>
+          <name>binding-rpc-broker</name>
+          <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+          prefix:binding-notification-service
+        </type>
+        <instance>
+          <name>binding-notification-broker</name>
+          <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+          prefix:binding-broker-osgi-registry
+        </type>
+        <instance>
+          <name>binding-osgi-broker</name>
+          <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker
+        </type>
+        <instance>
+          <name>binding-data-broker</name>
+          <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']
+          </provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+          prefix:kitchen-service
+        </type>
+        <instance>
+          <name>kitchen-service</name>
+          <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">
+          prefix:netconf-client-dispatcher
+        </type>
+        <instance>
+          <name>global-netconf-dispatcher</name>
+          <provider>/modules/module[type='netconf-client-dispatcher'][name='global-netconf-dispatcher']</provider>
+        </instance>
+      </service>
+    </services>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/logback-test.xml b/opendaylight/netconf/netconf-impl/src/test/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..74714a0
--- /dev/null
@@ -0,0 +1,13 @@
+<configuration scan="true">
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="error">
+    <appender-ref ref="STDOUT" />
+  </root>
+  <logger name="org.opendaylight.controller.netconf" level="TRACE"/>
+</configuration>
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/post-filter.xml
new file mode 100644 (file)
index 0000000..4abe6a3
--- /dev/null
@@ -0,0 +1,48 @@
+<!--
+  ~ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc-reply message-id="0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/pre-filter.xml
new file mode 100644 (file)
index 0000000..031409b
--- /dev/null
@@ -0,0 +1,40 @@
+<rpc-reply message-id="0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/0/request.xml
new file mode 100644 (file)
index 0000000..8d49a7f
--- /dev/null
@@ -0,0 +1,5 @@
+<rpc message-id="0"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <get>
+  </get>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/post-filter.xml
new file mode 100644 (file)
index 0000000..1ad3f20
--- /dev/null
@@ -0,0 +1,5 @@
+<rpc-reply message-id="1"
+           xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+  </data>
+</rpc-reply>
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/pre-filter.xml
new file mode 100644 (file)
index 0000000..8fd61e1
--- /dev/null
@@ -0,0 +1,40 @@
+<rpc-reply message-id="1" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/1/request.xml
new file mode 100644 (file)
index 0000000..2579aa6
--- /dev/null
@@ -0,0 +1,7 @@
+<rpc message-id="1"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <get>
+    <filter type="subtree">
+    </filter>
+  </get>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/post-filter.xml
new file mode 100644 (file)
index 0000000..e974b59
--- /dev/null
@@ -0,0 +1,35 @@
+<rpc-reply message-id="2" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/pre-filter.xml
new file mode 100644 (file)
index 0000000..a399e57
--- /dev/null
@@ -0,0 +1,48 @@
+<!--
+  ~ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc-reply message-id="2" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/2/request.xml
new file mode 100644 (file)
index 0000000..7b549b9
--- /dev/null
@@ -0,0 +1,13 @@
+<rpc message-id="2"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <get-config>
+    <source>
+      <running/>
+    </source>
+    <filter type="subtree">
+      <top xmlns="http://example.com/schema/1.2/config">
+        <users/>
+      </top>
+    </filter>
+  </get-config>
+</rpc>
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/post-filter.xml
new file mode 100644 (file)
index 0000000..e379d49
--- /dev/null
@@ -0,0 +1,26 @@
+<!--
+  ~ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc-reply message-id="3"
+           xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+        </user>
+        <user>
+          <name>fred</name>
+        </user>
+        <user>
+          <name>barney</name>
+        </user>
+      </users>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/pre-filter.xml
new file mode 100644 (file)
index 0000000..42f451b
--- /dev/null
@@ -0,0 +1,48 @@
+<!--
+  ~ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc-reply message-id="3" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/3/request.xml
new file mode 100644 (file)
index 0000000..771f136
--- /dev/null
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc message-id="3"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <get-config>
+    <source>
+      <running/>
+    </source>
+    <filter type="subtree">
+      <top xmlns="http://example.com/schema/1.2/config">
+        <users>
+          <user>
+            <name/>
+          </user>
+        </users>
+      </top>
+    </filter>
+  </get-config>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/post-filter.xml
new file mode 100644 (file)
index 0000000..c701ba0
--- /dev/null
@@ -0,0 +1,18 @@
+<rpc-reply message-id="4"
+           xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+      </users>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/pre-filter.xml
new file mode 100644 (file)
index 0000000..f2f2cbb
--- /dev/null
@@ -0,0 +1,48 @@
+<!--
+  ~ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc-reply message-id="4" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/4/request.xml
new file mode 100644 (file)
index 0000000..04c8149
--- /dev/null
@@ -0,0 +1,17 @@
+<rpc message-id="4"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <get-config>
+    <source>
+      <running/>
+    </source>
+    <filter type="subtree">
+      <top xmlns="http://example.com/schema/1.2/config">
+        <users>
+          <user>
+            <name>fred</name>
+          </user>
+        </users>
+      </top>
+    </filter>
+  </get-config>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/post-filter.xml
new file mode 100644 (file)
index 0000000..d6ffd00
--- /dev/null
@@ -0,0 +1,14 @@
+<rpc-reply message-id="5"
+           xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+        </user>
+      </users>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/pre-filter.xml
new file mode 100644 (file)
index 0000000..7e3f721
--- /dev/null
@@ -0,0 +1,40 @@
+<rpc-reply message-id="5" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/5/request.xml
new file mode 100644 (file)
index 0000000..3581988
--- /dev/null
@@ -0,0 +1,19 @@
+<rpc message-id="5"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <get-config>
+    <source>
+      <running/>
+    </source>
+    <filter type="subtree">
+      <top xmlns="http://example.com/schema/1.2/config">
+        <users>
+          <user>
+            <name>fred</name>
+            <type/>
+            <full-name/>
+          </user>
+        </users>
+      </top>
+    </filter>
+  </get-config>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/post-filter.xml
new file mode 100644 (file)
index 0000000..05eb019
--- /dev/null
@@ -0,0 +1,22 @@
+<rpc-reply message-id="6"
+           xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <company-info>
+            <id>2</id>
+          </company-info>
+        </user>
+      </users>
+    </top>
+  </data>
+</rpc-reply>
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/pre-filter.xml
new file mode 100644 (file)
index 0000000..71dd628
--- /dev/null
@@ -0,0 +1,48 @@
+<!--
+  ~ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+  ~
+  ~ This program and the accompanying materials are made available under the
+  ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+  -->
+
+<rpc-reply message-id="6" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/6/request.xml
new file mode 100644 (file)
index 0000000..c4a410d
--- /dev/null
@@ -0,0 +1,32 @@
+<rpc message-id="6"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <get-config>
+    <source>
+      <running/>
+    </source>
+    <filter type="subtree">
+      <top xmlns="http://example.com/schema/1.2/config">
+        <users>
+          <user>
+            <name>root</name>
+            <company-info/>
+          </user>
+          <user>
+            <name>fred</name>
+            <company-info>
+              <id/>
+            </company-info>
+          </user>
+          <user>
+            <name>barney</name>
+            <type>superuser</type>
+            <company-info>
+              <dept/>
+            </company-info>
+          </user>
+        </users>
+      </top>
+    </filter>
+  </get-config>
+</rpc>
+
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/post-filter.xml
new file mode 100644 (file)
index 0000000..676ba22
--- /dev/null
@@ -0,0 +1,13 @@
+<rpc-reply message-id="7"
+           xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <t:top xmlns:t="http://example.com/schema/1.2/stats">
+      <t:interfaces>
+        <t:interface t:ifName="eth0">
+          <t:ifInOctets>45621</t:ifInOctets>
+          <t:ifOutOctets>774344</t:ifOutOctets>
+        </t:interface>
+      </t:interfaces>
+    </t:top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/pre-filter.xml
new file mode 100644 (file)
index 0000000..ef88283
--- /dev/null
@@ -0,0 +1,52 @@
+<rpc-reply message-id="7" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <data>
+    <top xmlns="http://example.com/schema/1.2/config">
+      <users>
+        <user>
+          <name>root</name>
+          <type>superuser</type>
+          <full-name>Charlie Root</full-name>
+          <company-info>
+            <dept>1</dept>
+            <id>1</id>
+          </company-info>
+        </user>
+        <user>
+          <name>fred</name>
+          <type>admin</type>
+          <full-name>Fred Flintstone</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>2</id>
+          </company-info>
+        </user>
+        <user>
+          <name>barney</name>
+          <type>admin</type>
+          <full-name>Barney Rubble</full-name>
+          <company-info>
+            <dept>2</dept>
+            <id>3</id>
+          </company-info>
+        </user>
+      </users>
+      <groups>
+        <group>
+          <name>admin</name>
+        </group>
+      </groups>
+    </top>
+    <prefix:top xmlns:prefix="http://example.com/schema/1.2/stats">
+      <prefix:interfaces>
+        <prefix:interface prefix:ifName="eth0">
+          <prefix:ifInOctets>45621</prefix:ifInOctets>
+          <prefix:ifOutOctets>774344</prefix:ifOutOctets>
+        </prefix:interface>
+        <prefix:interface prefix:ifName="eth1">
+          <prefix:ifInOctets>1</prefix:ifInOctets>
+          <prefix:ifOutOctets>1</prefix:ifOutOctets>
+        </prefix:interface>
+      </prefix:interfaces>
+    </prefix:top>
+  </data>
+</rpc-reply>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/7/request.xml
new file mode 100644 (file)
index 0000000..4bbbaba
--- /dev/null
@@ -0,0 +1,12 @@
+<rpc message-id="7"
+     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+  <get>
+    <filter type="subtree">
+      <t:top xmlns:t="http://example.com/schema/1.2/stats">
+        <t:interfaces>
+          <t:interface t:ifName="eth0"/>
+        </t:interfaces>
+      </t:top>
+    </filter>
+  </get>
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/post-filter.xml
new file mode 100644 (file)
index 0000000..3498b02
--- /dev/null
@@ -0,0 +1,115 @@
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-6">
+  <data>
+    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:schema-service</type>
+        <instance>
+          <name>yang-schema-service</name>
+          <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
+        <instance>
+          <name>dom-broker</name>
+          <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-async-data-broker</type>
+        <instance>
+          <name>inmemory-data-broker</name>
+          <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>
+        <instance>
+          <name>global-netconf-processing-executor</name>
+          <provider>/modules/module[type='threadpool-flexible'][name='global-netconf-processing-executor']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
+        <instance>
+          <name>global-netconf-processing-executor-threadfactory</name>
+          <provider>/modules/module[type='threadfactory-naming'][name='global-netconf-processing-executor-threadfactory']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-dom-mapping-service</type>
+        <instance>
+          <name>runtime-mapping-singleton</name>
+          <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-timer</type>
+        <instance>
+          <name>global-timer</name>
+          <provider>/modules/module[type='netty-hashed-wheel-timer'][name='global-timer']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+        <instance>
+          <name>global-boss-group</name>
+          <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-boss-group']</provider>
+        </instance>
+        <instance>
+          <name>global-worker-group</name>
+          <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-worker-group']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>
+        <instance>
+          <name>global-event-executor</name>
+          <provider>/modules/module[type='netty-global-event-executor'][name='singleton']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-rpc-registry</type>
+        <instance>
+          <name>binding-rpc-broker</name>
+          <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</type>
+        <instance>
+          <name>binding-notification-broker</name>
+          <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>
+        <instance>
+          <name>binding-osgi-broker</name>
+          <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker</type>
+        <instance>
+          <name>binding-data-broker</name>
+          <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">prefix:kitchen-service</type>
+        <instance>
+          <name>kitchen-service</name>
+          <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">prefix:netconf-client-dispatcher</type>
+        <instance>
+          <name>global-netconf-dispatcher</name>
+          <provider>/modules/module[type='netconf-client-dispatcher'][name='global-netconf-dispatcher']</provider>
+        </instance>
+      </service>
+    </services>
+  </data>
+</rpc-reply>
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/pre-filter.xml
new file mode 100644 (file)
index 0000000..8a57b4c
--- /dev/null
@@ -0,0 +1,350 @@
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-6">
+  <data>
+    <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">prefix:toaster-provider-impl</type>
+        <name>toaster-provider-impl</name>
+        <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</type>
+          <name>binding-notification-broker</name>
+        </notification-service>
+        <rpc-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-rpc-registry</type>
+          <name>binding-rpc-broker</name>
+        </rpc-registry>
+        <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker</type>
+          <name>binding-data-broker</name>
+        </data-broker>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">prefix:sal-netconf-connector</type>
+        <name>controller-config</name>
+        <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">1830</port>
+        <connection-timeout-millis xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">20000</connection-timeout-millis>
+        <between-attempts-timeout-millis xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">2000</between-attempts-timeout-millis>
+        <sleep-factor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">1.5</sleep-factor>
+        <password xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">admin</password>
+        <dom-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
+          <name>dom-broker</name>
+        </dom-registry>
+        <client-dispatcher xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">prefix:netconf-client-dispatcher</type>
+          <name>global-netconf-dispatcher</name>
+        </client-dispatcher>
+        <username xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">admin</username>
+        <address xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">127.0.0.1</address>
+        <processing-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>
+          <name>global-netconf-processing-executor</name>
+        </processing-executor>
+        <tcp-only xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">false</tcp-only>
+        <binding-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>
+          <name>binding-osgi-broker</name>
+        </binding-registry>
+        <max-connection-attempts xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">0</max-connection-attempts>
+        <event-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>
+          <name>global-event-executor</name>
+        </event-executor>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">prefix:netconf-client-dispatcher</type>
+        <name>global-netconf-dispatcher</name>
+        <worker-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+          <name>global-worker-group</name>
+        </worker-thread-group>
+        <timer xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-timer</type>
+          <name>global-timer</name>
+        </timer>
+        <boss-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+          <name>global-boss-group</name>
+        </boss-thread-group>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:logback:config">prefix:logback</type>
+        <name>singleton</name>
+        <console-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <threshold-filter>ERROR</threshold-filter>
+          <name>STDOUT</name>
+          <encoder-pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</encoder-pattern>
+        </console-appenders>
+        <file-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <append>true</append>
+          <file-name>logs/audit.log</file-name>
+          <name>audit-file</name>
+          <encoder-pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} %msg %n</encoder-pattern>
+        </file-appenders>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>WARN</level>
+          <logger-name>org.opendaylight.controller.logging.bridge</logger-name>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>INFO</level>
+          <logger-name>audit</logger-name>
+          <appenders>audit-file</appenders>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>ERROR</level>
+          <logger-name>ROOT</logger-name>
+          <appenders>STDOUT</appenders>
+          <appenders>opendaylight.log</appenders>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>INFO</level>
+          <logger-name>org.opendaylight</logger-name>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>INFO</level>
+          <logger-name>org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort</logger-name>
+          <appenders>opendaylight.log</appenders>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>TRACE</level>
+          <logger-name>org.opendaylight.controller.netconf</logger-name>
+        </loggers>
+        <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <level>WARN</level>
+          <logger-name>io.netty</logger-name>
+        </loggers>
+        <rolling-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
+          <append>true</append>
+          <max-file-size>10MB</max-file-size>
+          <file-name>logs/opendaylight.log</file-name>
+          <name>opendaylight.log</name>
+          <file-name-pattern>logs/opendaylight.%d.log.zip</file-name-pattern>
+          <encoder-pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n</encoder-pattern>
+          <clean-history-on-start>false</clean-history-on-start>
+          <max-history>1</max-history>
+          <rolling-policy-type>TimeBasedRollingPolicy</rolling-policy-type>
+        </rolling-appenders>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl">prefix:shutdown</type>
+        <name>shutdown</name>
+        <secret xmlns="urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl"/>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty:timer">prefix:netty-hashed-wheel-timer</type>
+        <name>global-timer</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">prefix:netty-threadgroup-fixed</type>
+        <name>global-boss-group</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup">prefix:netty-threadgroup-fixed</type>
+        <name>global-worker-group</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
+        <name>yang-schema-service</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
+        <name>inmemory-dom-broker</name>
+        <async-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-async-data-broker</type>
+          <name>inmemory-data-broker</name>
+        </async-data-broker>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
+        <name>inmemory-data-broker</name>
+        <schema-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:schema-service</type>
+          <name>yang-schema-service</name>
+        </schema-service>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">prefix:threadpool-flexible</type>
+        <name>global-netconf-processing-executor</name>
+        <threadFactory xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
+          <name>global-netconf-processing-executor-threadfactory</name>
+        </threadFactory>
+        <minThreadCount xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">1</minThreadCount>
+        <max-thread-count xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">4</max-thread-count>
+        <keepAliveMillis xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">600000</keepAliveMillis>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor">prefix:netty-global-event-executor</type>
+        <name>singleton</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
+        <name>binding-broker-impl</name>
+        <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</type>
+          <name>binding-notification-broker</name>
+        </notification-service>
+        <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker</type>
+          <name>binding-data-broker</name>
+        </data-broker>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
+        <name>runtime-mapping-singleton</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
+        <name>binding-notification-broker</name>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-compatible-broker</type>
+        <name>inmemory-binding-data-broker</name>
+        <dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
+          <name>dom-broker</name>
+        </dom-async-broker>
+        <binding-mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-dom-mapping-service</type>
+          <name>runtime-mapping-singleton</name>
+        </binding-mapping-service>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">prefix:threadfactory-naming</type>
+        <name>global-netconf-processing-executor-threadfactory</name>
+        <name-prefix xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">remote-connector-processing-executor</name-prefix>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">prefix:kitchen-service-impl</type>
+        <name>kitchen-service-impl</name>
+        <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</type>
+          <name>binding-notification-broker</name>
+        </notification-service>
+        <rpc-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-rpc-registry</type>
+          <name>binding-rpc-broker</name>
+        </rpc-registry>
+      </module>
+      <module>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">prefix:remote-zeromq-rpc-server</type>
+        <name>remoter</name>
+        <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
+        <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
+          <name>dom-broker</name>
+        </dom-broker>
+      </module>
+    </modules>
+    <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:schema-service</type>
+        <instance>
+          <name>yang-schema-service</name>
+          <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
+        <instance>
+          <name>dom-broker</name>
+          <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-async-data-broker</type>
+        <instance>
+          <name>inmemory-data-broker</name>
+          <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadpool</type>
+        <instance>
+          <name>global-netconf-processing-executor</name>
+          <provider>/modules/module[type='threadpool-flexible'][name='global-netconf-processing-executor']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
+        <instance>
+          <name>global-netconf-processing-executor-threadfactory</name>
+          <provider>/modules/module[type='threadfactory-naming'][name='global-netconf-processing-executor-threadfactory']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-dom-mapping-service</type>
+        <instance>
+          <name>runtime-mapping-singleton</name>
+          <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-timer</type>
+        <instance>
+          <name>global-timer</name>
+          <provider>/modules/module[type='netty-hashed-wheel-timer'][name='global-timer']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+        <instance>
+          <name>global-boss-group</name>
+          <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-boss-group']</provider>
+        </instance>
+        <instance>
+          <name>global-worker-group</name>
+          <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-worker-group']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>
+        <instance>
+          <name>global-event-executor</name>
+          <provider>/modules/module[type='netty-global-event-executor'][name='singleton']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-rpc-registry</type>
+        <instance>
+          <name>binding-rpc-broker</name>
+          <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</type>
+        <instance>
+          <name>binding-notification-broker</name>
+          <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>
+        <instance>
+          <name>binding-osgi-broker</name>
+          <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker</type>
+        <instance>
+          <name>binding-data-broker</name>
+          <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">prefix:kitchen-service</type>
+        <instance>
+          <name>kitchen-service</name>
+          <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
+        </instance>
+      </service>
+      <service>
+        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf">prefix:netconf-client-dispatcher</type>
+        <instance>
+          <name>global-netconf-dispatcher</name>
+          <provider>/modules/module[type='netconf-client-dispatcher'][name='global-netconf-dispatcher']</provider>
+        </instance>
+      </service>
+    </services>
+  </data>
+</rpc-reply>
diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/8/request.xml
new file mode 100644 (file)
index 0000000..4d71ba4
--- /dev/null
@@ -0,0 +1,12 @@
+<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="m-10">
+  <get-config>
+    <filter xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:type="subtree">
+      <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <service/>
+      </services>
+    </filter>
+    <source>
+      <running/>
+    </source>
+  </get-config>
+</rpc>
index c277e20553fb3ed469c9f849d624f795f0acf635..fa78fa4bd3983c7eee4cb166e54bc5692f0bad54 100644 (file)
@@ -8,15 +8,16 @@
 package org.opendaylight.controller.netconf.monitoring;
 
 import com.google.common.collect.Maps;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.monitoring.xml.JaxBSerializer;
 import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 731aad6d1a4d7103ca12fc99541482b81a82757b..e9e92d9202297c626d57e02bcd173beed9ebdc13 100644 (file)
@@ -20,7 +20,7 @@ import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
 
 public class NetconfMonitoringOperationService implements NetconfOperationService {
 
-    public static final Set<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
+    private static final Set<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
 
         @Override
         public String getCapabilityUri() {
index 9e287f99210389e41ba8d4cbd6f5509b1abfeaef..1b0a34d7e0fa7d0b6ab32c6c3600de52a5f1543f 100644 (file)
@@ -11,7 +11,7 @@ package org.opendaylight.controller.netconf.nettyutil.handler.exi;
 import java.util.List;
 
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.openexi.proc.common.EXIOptions;
 import org.w3c.dom.Document;
index 4e32e82e89251089b8425fe3a990ab46fb22cace..2bda51b495c3505741ff9c697712cb3f98a2b1ee 100644 (file)
@@ -30,7 +30,7 @@ public class SSHTest {
         AuthProvider authProvider = mock(AuthProvider.class);
         doReturn(PEMGenerator.generate().toCharArray()).when(authProvider).getPEMAsCharArray();
         doReturn(true).when(authProvider).authenticated(anyString(), anyString());
-        NetconfSSHServer thread = NetconfSSHServer.start(1831, NetconfConfigUtil.getNetconfLocalAddress(), authProvider, new NioEventLoopGroup());
+        NetconfSSHServer thread = NetconfSSHServer.start(10831, NetconfConfigUtil.getNetconfLocalAddress(), authProvider, new NioEventLoopGroup());
         Thread.sleep(2000);
         logger.info("Closing socket");
         thread.close();
index d9d957c663766ccb847cc57a3cde920b19d6cfd2..f3b35ce3ceaee5b6b26aee7ebac6892e16ef47b6 100644 (file)
@@ -59,7 +59,8 @@
             <Import-Package>com.google.common.base, com.google.common.collect, io.netty.channel,
               io.netty.util.concurrent, javax.annotation, javax.xml.namespace, javax.xml.parsers, javax.xml.transform,
               javax.xml.transform.dom, javax.xml.transform.stream, javax.xml.validation, javax.xml.xpath,
-              org.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.mapping.api,
+              org.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.api.xml,
+              org.opendaylight.controller.netconf.mapping.api,
               org.osgi.framework, org.slf4j, org.w3c.dom, org.xml.sax,io.netty.channel.local</Import-Package>
             <Export-Package>org.opendaylight.controller.netconf.util.*</Export-Package>
           </instructions>
index 640596d93078b86b356bc18c19d318bab89a62c6..0269bcccb989492e69b616fc955545ca49509f31 100644 (file)
@@ -8,9 +8,10 @@
 package org.opendaylight.controller.netconf.util;
 
 import com.google.common.base.Preconditions;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 65ca1b7c4b5118b00653aa5daf9d0416342532ef..25e0f7926574c3168bc013cff865ec2f6a8a33db 100644 (file)
@@ -11,11 +11,11 @@ package org.opendaylight.controller.netconf.util.mapping;
 import java.util.Map;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,12 +47,12 @@ public abstract class AbstractNetconfOperation implements NetconfOperation {
 
     public static final class OperationNameAndNamespace {
         private final String operationName, namespace;
+        private final XmlElement operationElement;
 
         public OperationNameAndNamespace(Document message) throws NetconfDocumentedException {
             XmlElement requestElement = null;
             requestElement = getRequestElementWithCheck(message);
-
-            XmlElement operationElement = requestElement.getOnlyChildElement();
+            operationElement = requestElement.getOnlyChildElement();
             operationName = operationElement.getName();
             namespace = operationElement.getNamespace();
         }
@@ -64,6 +64,10 @@ public abstract class AbstractNetconfOperation implements NetconfOperation {
         public String getNamespace() {
             return namespace;
         }
+
+        public XmlElement getOperationElement() {
+            return operationElement;
+        }
     }
 
     protected static XmlElement getRequestElementWithCheck(Document message) throws NetconfDocumentedException {
index 86b2ba1671478a022e30f7dd8c724b07c1d4d703..33934d10ba1c8ec9db8b29fe2135eda9cdcf499b 100644 (file)
@@ -13,9 +13,9 @@ import org.opendaylight.controller.netconf.api.NetconfMessage;
 import java.util.Set;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
index 49395d53d21225a20b6d47491db0e05fd03626eb..3e8040ad8a1d87e916415795e08e38814963537b 100644 (file)
@@ -10,15 +10,17 @@ package org.opendaylight.controller.netconf.util.messages;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Collections2;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
 import javax.annotation.Nullable;
+
 import java.util.Collection;
 import java.util.List;
 
index fdcaa2a5b8c98616385231d5c6c8c0f7e39c0adc..4c4ff2fc583a0a1007ccd4b4706054c097eb2d0c 100644 (file)
@@ -9,14 +9,15 @@
 package org.opendaylight.controller.netconf.util.messages;
 
 import com.google.common.base.Preconditions;
+
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
+
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -24,12 +25,6 @@ import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import java.io.InputStream;
-import java.util.Map.Entry;
 
 public final class SendErrorExceptionUtil {
     private static final Logger logger = LoggerFactory.getLogger(SendErrorExceptionUtil.class);
@@ -86,56 +81,8 @@ public final class SendErrorExceptionUtil {
         }
     }
 
-    private static XPathExpression rpcErrorExpression = XMLNetconfUtil
-            .compileXPath("/netconf:rpc-reply/netconf:rpc-error");
-    private static XPathExpression errorTypeExpression = XMLNetconfUtil.compileXPath("netconf:error-type");
-    private static XPathExpression errorTagExpression = XMLNetconfUtil.compileXPath("netconf:error-tag");
-    private static XPathExpression errorSeverityExpression = XMLNetconfUtil.compileXPath("netconf:error-severity");
-
     private static Document createDocument(final NetconfDocumentedException sendErrorException) {
-
-        final InputStream errIS = SendErrorExceptionUtil.class.getResourceAsStream("server_error.xml");
-        Document originalErrorDocument;
-        try {
-            originalErrorDocument = XmlUtil.readXmlToDocument(errIS);
-        } catch (final Exception e) {
-            throw new IllegalStateException(e);
-        }
-
-        final Document errorDocument = XmlUtil.createDocumentCopy(originalErrorDocument);
-        final Node rootNode = errorDocument.getFirstChild();
-
-        final Node rpcErrorNode = (Node) XmlUtil.evaluateXPath(rpcErrorExpression, rootNode, XPathConstants.NODE);
-
-        final Node errorTypeNode = (Node) XmlUtil.evaluateXPath(errorTypeExpression, rpcErrorNode, XPathConstants.NODE);
-        errorTypeNode.setTextContent(sendErrorException.getErrorType().getTagValue());
-
-        final Node errorTagNode = (Node) XmlUtil.evaluateXPath(errorTagExpression, rpcErrorNode, XPathConstants.NODE);
-        errorTagNode.setTextContent(sendErrorException.getErrorTag().getTagValue());
-
-        final Node errorSeverityNode = (Node) XmlUtil.evaluateXPath(errorSeverityExpression, rpcErrorNode,
-                XPathConstants.NODE);
-        errorSeverityNode.setTextContent(sendErrorException.getErrorSeverity().getTagValue());
-
-        if (sendErrorException.getErrorInfo() != null && !sendErrorException.getErrorInfo().isEmpty()) {
-            /*
-             * <error-info> <bad-attribute>message-id</bad-attribute>
-             * <bad-element>rpc</bad-element> </error-info>
-             */
-            final Node errorInfoNode = errorDocument.createElementNS(
-                    XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, "error-info");
-
-            errorInfoNode.setPrefix(rootNode.getPrefix());
-            rpcErrorNode.appendChild(errorInfoNode);
-            for (final Entry<String, String> errorInfoEntry : sendErrorException.getErrorInfo().entrySet()) {
-                final Node node = errorDocument.createElementNS(
-                        XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, errorInfoEntry.getKey());
-                node.setTextContent(errorInfoEntry.getValue());
-                errorInfoNode.appendChild(node);
-            }
-
-        }
-        return errorDocument;
+        return sendErrorException.toXMLDocument();
     }
 
     /**
index 02ced96bf30d6cc6f6ae619f3b32053dbe17f4d8..e7ce4541559943e86983e2e83285ff0d0b9c18e6 100644 (file)
@@ -13,6 +13,8 @@ import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
 
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+
 public final class XMLNetconfUtil {
 
     private XMLNetconfUtil() {}
index ac200a0aa668c1a406e044e11205ac90c20fc478..8780925eb185b97493cfc7557620f2846604ecd4 100644 (file)
@@ -338,6 +338,17 @@ public final class XmlElement {
         );
     }
 
+    public Optional<String> getOnlyTextContentOptionally() {
+        // only return text content if this node has exactly one Text child node
+        if (element.getChildNodes().getLength() == 1) {
+            Node item = element.getChildNodes().item(0);
+            if (item instanceof Text) {
+                return Optional.of(((Text) item).getWholeText());
+            }
+        }
+        return Optional.absent();
+    }
+
     public String getNamespaceAttribute() throws MissingNameSpaceException {
         String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY);
         if (attribute == null || attribute.equals("")){
index b2b202b69ef024569d032771ecd35e116812769e..01b1c8d5642368cfcfb76249ffd163037616134a 100644 (file)
@@ -10,12 +10,14 @@ package org.opendaylight.controller.netconf.util.xml;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
+
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringWriter;
+
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilder;
@@ -33,6 +35,8 @@ import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
+
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
diff --git a/opendaylight/northbound/swagger-ui/pom.xml b/opendaylight/northbound/swagger-ui/pom.xml
new file mode 100644 (file)
index 0000000..18eaed9
--- /dev/null
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <artifactId>swagger-ui</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <api.dir>${resource.dir}/apis</api.dir>
+    <resource.dir>${project.build.directory}/classes</resource.dir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>javax.servlet</artifactId>
+    </dependency>
+    <!-- add dependency on all northbound bundles -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>connectionmanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>controllermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>flowprogrammer.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwarding.staticrouting.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.bridgedomain.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>statistics.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>subnets.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topology.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>usermanager.northbound</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package></Export-Package>
+            <Import-Package>org.slf4j,
+              javax.annotation,
+              javax.naming,
+              javax.servlet,
+              javax.servlet.annotation,
+              javax.servlet.http,
+              com.google.gson,</Import-Package>
+            <Export-Package></Export-Package>
+            <Include-Resource>apis=target/classes/apis,
+                index.html=target/classes/index.html,
+                apilist.json=target/classes/apilist.json,
+                css=target/classes/css,
+                lib=target/classes/lib,
+                swagger-ui.min.js=target/classes/swagger-ui.min.js,
+                swagger-ui.js=target/classes/swagger-ui.js,
+                images=target/classes/images,
+                WEB-INF/web.xml=target/classes/WEB-INF/web.xml</Include-Resource>
+            <Web-ContextPath>/swagger</Web-ContextPath>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.7</version>
+        <dependencies>
+          <dependency>
+            <groupId>ant-contrib</groupId>
+            <artifactId>ant-contrib</artifactId>
+            <version>1.0b3</version>
+            <exclusions>
+              <exclusion>
+                <groupId>ant</groupId>
+                <artifactId>ant</artifactId>
+              </exclusion>
+            </exclusions>
+          </dependency>
+        </dependencies>
+        <executions>
+          <execution>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <phase>generate-sources</phase>
+            <configuration>
+              <target>
+                <taskdef classpathref="maven.plugin.classpath" resource="net/sf/antcontrib/antlib.xml"></taskdef>
+                <patternset id="rest.paths">
+                  <include name="**/enunciate/generate/swagger/ui/*.json"></include>
+                  <exclude name="**/java-client/**"></exclude>
+                  <exclude name="**/swagger-ui/**"></exclude>
+                </patternset>
+
+                <echo message="======== Assembling swagger docs ========"></echo>
+                <!-- make api directory -->
+                <mkdir dir="${api.dir}"></mkdir>
+                <!--  copy swagger libs -->
+                <copy todir="${resource.dir}">
+                  <fileset dir="../subnets/target/enunciate/generate/swagger/ui">
+                    <exclude name="**/*.json"></exclude>
+                    <exclude name="**/*.png"></exclude>
+                    <exclude name="**/index.html"></exclude>
+                  </fileset>
+                </copy>
+                <!--  Copy NorthBound json files into ui directory-->
+                <copy todir="${api.dir}">
+                  <fileset dir="${basedir}/../../..">
+                    <patternset refid="rest.paths"></patternset>
+                  </fileset>
+                  <mapper>
+                    <regexpmapper from="^(.*)/([^/]+)/*/target/enunciate/generate/swagger/ui/(.*Northbound).*$$" to="\3"></regexpmapper>
+                    <regexpmapper from="^(.*)/([^/]+)/*/target/enunciate/generate/swagger/ui/(.*resource-list.json)$$" to="\2-\3"></regexpmapper>
+                  </mapper>
+                </copy>
+
+                <!--  Correct base path -->
+                <replaceregexp match="/full" replace="">
+                  <fileset dir="${api.dir}">
+                    <include name="**/*Northbound"></include>
+                  </fileset>
+                </replaceregexp>
+                <!--  Merge Resource list -->
+                <echo append="false" file="${resource.dir}/apilist.json">{
+  "swaggerVersion": "1.1",
+  "basePath": "http://localhost:8080/swagger/apis",
+  "apis": [</echo>
+                <for param="file">
+                  <path>
+                    <fileset dir="${api.dir}">
+                      <include name="**/*resource-list.json"></include>
+                      <exclude name="**/neutron*"></exclude>
+                    </fileset>
+                  </path>
+                  <sequential>
+                    <echo message="Processing json resource @{file}"></echo>
+                    <loadfile property="jsoncontent" srcfile="@{file}">
+                      <filterchain>
+                        <headfilter lines="10"></headfilter>
+                        <tailfilter lines="6"></tailfilter>
+                      </filterchain>
+                    </loadfile>
+                    <echo append="true" file="${resource.dir}/apilist.json" message="${jsoncontent},"></echo>
+                    <var name="jsoncontent" unset="true"></var>
+                  </sequential>
+                </for>
+                <sequential>
+                  <loadfile property="jsoncontent" srcfile="${api.dir}/neutron-resource-list.json">
+                    <filterchain>
+                      <headfilter lines="46"></headfilter>
+                      <tailfilter lines="42"></tailfilter>
+                    </filterchain>
+                  </loadfile>
+                  <echo append="true" file="${resource.dir}/apilist.json" message="${jsoncontent},"></echo>
+                  <var name="jsoncontent" unset="true"></var>
+                </sequential>
+                <echo append="true" file="${resource.dir}/apilist.json">{ }
+  ]
+}</echo>
+
+                <!-- Remove .json from api paths -->
+                <replaceregexp file="${resource.dir}/apilist.json" flags="g" match=".json" replace=""></replaceregexp>
+                <replaceregexp file="${resource.dir}/apilist.json" flags="g" match="JAXRS" replace=""></replaceregexp>
+
+                <!-- cleanup resource files as we don't need them -->
+                <delete>
+                  <fileset dir="${api.dir}" includes="**/*resource-list.json"></fileset>
+                </delete>
+                <echo message="======== Build successful ========"></echo>
+              </target>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+  </scm>
+</project>
diff --git a/opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java b/opendaylight/northbound/swagger-ui/src/main/java/org/opendaylight/controller/swaggerui/BasePathModifierServlet.java
new file mode 100644 (file)
index 0000000..083a50c
--- /dev/null
@@ -0,0 +1,101 @@
+package org.opendaylight.controller.swaggerui;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+/**
+ * Servlet implementation class BasePathModifierServlet
+ */
+public class BasePathModifierServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+    private static final Logger logger = LoggerFactory
+            .getLogger(BasePathModifierServlet.class);
+
+    private static final String API_BASE_PATH_SUFFIX = "/swagger/apis";
+    private static final String BASE_PATH_KEY = "basePath";
+
+    /**
+     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
+     *      response)
+     */
+    @Override
+    protected void doGet(HttpServletRequest request,
+            HttpServletResponse response) throws ServletException, IOException {
+        String resourcePath = request.getRequestURI().substring(
+                request.getContextPath().length());
+        logger.debug("Locating resource : {}.", resourcePath);
+        JsonObject jsonObject = null;
+        try {
+
+            InputStream stream = this.getServletContext().getResourceAsStream(
+                    resourcePath);
+            if (stream == null) {
+                response.sendError(HttpServletResponse.SC_NOT_FOUND,
+                        "API / API Listing not found");
+                return;
+            }
+            BufferedReader streamReader = new BufferedReader(
+                    new InputStreamReader(stream, "UTF-8"));
+            StringBuilder responseStrBuilder = new StringBuilder();
+
+            String inputStr;
+            while ((inputStr = streamReader.readLine()) != null)
+                responseStrBuilder.append(inputStr);
+
+            JsonElement jelement = new JsonParser().parse(responseStrBuilder
+                    .toString());
+            jsonObject = jelement.getAsJsonObject();
+
+            String basePath = jsonObject.get(BASE_PATH_KEY).getAsString();
+
+            // construct base path
+            StringBuilder requestURL = new StringBuilder();
+
+            requestURL.append(request.isSecure() ? "https://" : "http://")
+                    .append(request.getServerName()).append(":")
+                    .append(request.getServerPort());
+            if (!basePath.contains(requestURL)) {
+                String endPath = "";
+                if (basePath.contains(API_BASE_PATH_SUFFIX)) {
+                    endPath = basePath.substring(basePath
+                            .indexOf(API_BASE_PATH_SUFFIX));
+                }
+                basePath = requestURL + endPath;
+                logger.debug("Modified Base Path is {}", basePath);
+                jsonObject.addProperty(BASE_PATH_KEY, basePath);
+            }
+        } catch (Exception ex) {
+            logger.error("Error processing JSON data", ex);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "Could not read API Listing or APIs");
+            return;
+        }
+
+        try {
+            response.setContentType("application/json");
+            PrintWriter out = response.getWriter();
+            out.print(jsonObject);
+            out.flush();
+        } catch (Exception ex) {
+            logger.error("Error while writing response", ex);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "Internal Error while writing resposne");
+        }
+    }
+
+}
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml b/opendaylight/northbound/swagger-ui/src/main/resources/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..6d02390
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+  <servlet>
+     <servlet-name>BasePathModifierServlet</servlet-name>
+     <servlet-class>org.opendaylight.controller.swaggerui.BasePathModifierServlet</servlet-class>
+  </servlet>
+  <!-- Mapping for all northbound json files aka apis-->
+  <servlet-mapping>
+    <servlet-name>BasePathModifierServlet</servlet-name>
+    <url-pattern>/apis/*</url-pattern>
+  </servlet-mapping>
+  <!-- Mapping to get list of available NB apis -->
+  <servlet-mapping>
+    <servlet-name>BasePathModifierServlet</servlet-name>
+    <url-pattern>/apilist.json</url-pattern>
+  </servlet-mapping>
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+</web-app>
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css b/opendaylight/northbound/swagger-ui/src/main/resources/css/custom.css
new file mode 100644 (file)
index 0000000..e393943
--- /dev/null
@@ -0,0 +1,12 @@
+body #header a#logo {
+    font-size: 1.5em;
+    font-weight: bold;
+    text-decoration: none;
+    background: transparent url(../images/logo.png) no-repeat left center;
+    padding: 20px 0 20px 70px;
+    color: white;
+}
+
+div.footer {
+    display: none;
+}
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png b/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png
new file mode 100644 (file)
index 0000000..d49fb86
Binary files /dev/null and b/opendaylight/northbound/swagger-ui/src/main/resources/images/logo.png differ
diff --git a/opendaylight/northbound/swagger-ui/src/main/resources/index.html b/opendaylight/northbound/swagger-ui/src/main/resources/index.html
new file mode 100644 (file)
index 0000000..bb5126c
--- /dev/null
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Swagger UI</title>
+    <link href='//fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>
+    <link href='css/highlight.default.css' media='screen' rel='stylesheet' type='text/css'/>
+    <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
+    <link href='css/custom.css' media='screen' rel='stylesheet' type='text/css'/>
+    <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
+    <script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
+    <script src='lib/handlebars-1.0.rc.1.js' type='text/javascript'></script>
+    <script src='lib/underscore-min.js' type='text/javascript'></script>
+    <script src='lib/backbone-min.js' type='text/javascript'></script>
+    <script src='lib/swagger.js' type='text/javascript'></script>
+    <script src='swagger-ui.js' type='text/javascript'></script>
+    <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
+
+    <script type="text/javascript">
+    $(function () {
+        window.swaggerUi = new SwaggerUi({
+                discoveryUrl:"./apilist.json",
+                apiKey:"",
+                dom_id:"swagger-ui-container",
+                supportHeaderParams: false,
+                supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
+                onComplete: function(swaggerApi, swaggerUi){
+                    if(console) {
+                        console.log("Loaded SwaggerUI")
+                        console.log(swaggerApi);
+                        console.log(swaggerUi);
+                    }
+                  $('pre code').each(function(i, e) {hljs.highlightBlock(e)});
+                },
+                onFailure: function(data) {
+                    if(console) {
+                        console.log("Unable to Load SwaggerUI");
+                        console.log(data);
+                    }
+                },
+                docExpansion: "none"
+            });
+
+            window.swaggerUi.load();
+        });
+
+    </script>
+</head>
+
+<body>
+  <div id='header'>
+    <div class="swagger-ui-wrap">
+      <a id="logo" href="http://www.opendaylight.org/">ODL NB API</a>
+      <form id='api_selector'>
+        <div class='input'>
+          <input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/>
+        </div>
+        <div class='input'>
+          <input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/>
+        </div>
+        <div class='input'><a id="explore" href="#">Explore</a></div>
+      </form>
+    </div>
+  </div>
+
+  <div id="message-bar" class="swagger-ui-wrap">
+      &nbsp;
+  </div>
+
+  <div id="swagger-ui-container" class="swagger-ui-wrap">
+
+  </div>
+
+</body>
+
+</html>
index b2cb414303fa2a826f9b9a3ebfc0ab7f7365da88..7bd15ff7f45c2aa56bfde10a4878ac55371fc533 100644 (file)
@@ -111,7 +111,9 @@ public class ConnectionService implements IPluginOutConnectionService, IConnecti
     @Override
     public Node connect (String type, String connectionIdentifier, Map<ConnectionConstants, String> params) {
         IPluginInConnectionService s = pluginService.get(type);
-        if (s != null) return s.connect(connectionIdentifier, params);
+        if (s != null) {
+            return s.connect(connectionIdentifier, params);
+        }
         return null;
     }
 
@@ -121,7 +123,9 @@ public class ConnectionService implements IPluginOutConnectionService, IConnecti
             for (String pluginType : this.pluginService.keySet()) {
                 IPluginInConnectionService s = pluginService.get(pluginType);
                 Node node = s.connect(connectionIdentifier, params);
-                if (node != null) return node;
+                if (node != null) {
+                    return node;
+                }
             }
         }
         return null;
diff --git a/pom.xml b/pom.xml
index a26533819c45e8a8a89d696eef00093551db1b49..c54d9a930f28ad39ad680f30314508248bd2eea5 100644 (file)
--- a/pom.xml
+++ b/pom.xml
       </activation>
       <modules>
         <module>opendaylight/northbound/java-client</module>
+        <module>opendaylight/northbound/swagger-ui</module>
       </modules>
     </profile>
   </profiles>