Document usage of Binding Query Language 09/94809/7
authorKonstantin.Nosach <Kostiantyn.Nosach@pantheon.tech>
Tue, 26 Jan 2021 10:50:33 +0000 (12:50 +0200)
committerRobert Varga <nite@hq.sk>
Mon, 15 Feb 2021 13:33:21 +0000 (13:33 +0000)
Adds documentation specific to the developer guide:
- Compears two approaches for retrieving data from storage
- Read-like operation (old one approach)
- Query-like operation (new one approach)

JIRA: MDSAL-656
Change-Id: Ie84224a584256f411d63b0ecb900f341f9fa3d35
Signed-off-by: Kostiantyn Nosach <kostiantyn.nosach@pantheon.tech>
docs/index.rst
docs/query-binding-language-developer-guide.rst [new file with mode: 0644]

index a80c860b20cd83ca75904abbfdf476b8b39159bf..12dd30153978d9623a1b971ff2878642dd397038 100644 (file)
@@ -125,3 +125,4 @@ Table of Contents
    architecture
    conceptual-data-tree
    incremental-backup
+   query-binding-language-developer-guide
diff --git a/docs/query-binding-language-developer-guide.rst b/docs/query-binding-language-developer-guide.rst
new file mode 100644 (file)
index 0000000..dedfabe
--- /dev/null
@@ -0,0 +1,108 @@
+.. _mdsal-binding-dev-guide:
+
+MD-SAL Binding Query Language Developer Guide
+=============================================
+
+.. note::
+
+       Reading this section is likely useful as it contains an overview
+       of MD-SAL Binding query language in OpenDaylight and a how-to use it for
+       retrieving data from data storage.
+
+Retrieving data from storage
+----------------------------
+
+MD-SAL has two ways (operations) of retrieving data from storage: read-like and query-like operations.
+
+Read-like operation
+~~~~~~~~~~~~~~~~~~~
+
+The method **read** of ReadTransaction interface.
+
+::
+
+       <T extends DataObject> FluentFuture<Optional<T>> read(LogicalDatastoreType store, InstanceIdentifier<T> path);
+
+The method reads data from the provided logical data store located at the provided path.
+If the target is a subtree, then the whole subtree is read (and will be accessible from the returned DataObject).
+So we are getting DataObject which we need to process in code for getting relevant data:
+
+::
+
+    FluentFuture<Optional<Foo>> future;
+    try (ReadTransaction rtx = getDataBroker().newReadOnlyTransaction()) {
+        future = rtx.read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Foo.class));
+    }
+    Foo haystack = future.get().orElseThrow();
+    Object result = null;
+    for (System system : haystack.nonnullSystem().values()) {
+        if (needle.equals(system.getAlias())) {
+            result = system;
+            break;
+        }
+    }
+
+.. note::
+
+       The structure of the Foo container is `here`_.
+
+.. _here: https://github.com/opendaylight/mdsal/blob/master/binding/mdsal-binding-test-model/src/main/yang/mdsal-query.yang
+
+Query-like operation
+~~~~~~~~~~~~~~~~~~~~
+
+The method **execute** of QueryReadTransaction interface.
+
+::
+
+       <T extends DataObject> FluentFuture<QueryResult<T>> execute(LogicalDatastoreType store, QueryExpression<T> query);
+
+The method executes a query on the provided logical data store for getting relevant data.
+So we are getting result which we need for future business logic processing.
+Before running the method execute we need to prepare a query with the match predicates.
+For example, we want to find in Foo container the System with alias **target-needle**:
+
+::
+
+    String needle = "target-needle";
+    QueryExpression<System> query = factory.querySubtree(InstanceIdentifier.create(Foo.class))
+        .extractChild(System.class)
+            .matching()
+                .leaf(System::getAlias).valueEquals(needle)
+            .build();
+
+The method **querySubtree** creates a new **DescendantQueryBuilder** for a specified root path. It's intermediate query builder stage,
+which allows the specification of the query result type to be built up via **extractChild(Class)** and
+**extractChild(Class, Class)** methods. They used to specify which object type to select from the root path.
+Once completed, use either **build()** to create a simple query, or **matching()** to transition to specify predicates.
+There is a bunch of overloaded methods **leaf** which based on the type of arguments returns specific match builders:
+
+- ValueMatchBuilder methods:
+
+| **ValueMatch<T> nonNull();**
+| **ValueMatch<T> isNull();**
+| **ValueMatch<T> valueEquals(V value);**
+
+- ComparableMatchBuilder extends ValueMatchBuilder and adds methods:
+
+| **ValueMatch<T> lessThan(V value);**
+| **ValueMatch<T> lessThanOrEqual(V value);**
+| **ValueMatch<T> greaterThan(V value);**
+| **ValueMatch<T> greaterThanOrEqual(V value);**
+
+- StringMatchBuilder extends ValueMatchBuilder and adds methods:
+
+| **ValueMatch<T> startsWith(String str);**
+| **ValueMatch<T> endsWith(String str);**
+| **ValueMatch<T> contains(String str);**
+| **ValueMatch<T> matchesPattern(Pattern pattern);**
+
+After creation of query, we can use it in the method execute of QueryReadTransaction interface:
+
+::
+
+    FluentFuture<QueryResult<System>> future;
+    try (ReadTransaction rtx = getDataBroker().newReadOnlyTransaction()) {
+        future = ((QueryReadTransaction) rtx).execute(LogicalDatastoreType.CONFIGURATION, query);
+    }
+    QueryResult<System> result = future.get();
\ No newline at end of file