Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

On data conversion from String to DataNode object there is an intermediate stage of data being represented as 
a NormalizedNode instance which is a Yang Tools library artifact.

The NormalizedNode represents the list node element as a single object. It means the data fragment which
represents the list element with multiple entries can be successfully converted into NormalizedNode.

However the subsequent NormalizedNode to DataNode conversion performed by CPS internal logic supports only
single DataNode object as top level element. The functionality of DataNodeBuilder require to be extended 
in order to convert the list element data (fragment) into collection of DataNode objects

The JSON String to NormalizedNode conversion
then followed by NormalizedNode to DataNode conversion.

These data structures are different.

draw.io Diagram
borderfalse
diagramNamecps-list-node-transformation-diagram
simpleViewerfalse
width
linksauto
tbstyleinline
diagramDisplayName
lboxfalse
diagramWidth741
revision2

While list node element is a single node within a NormalizedNode structure, on transformation to DataNode
the original list node wrapper is omitted (as containing no actual data) and list elements became a nodes belonging
to upper level parent node.

In a context of a data fragment the single root level node became a collection of nodes after transformation,
so all the subsequent operations require to be performed using a collection of nodes, not the single one.

In current implementation the CPS conversion to DataNode always returns single node result even if multiple
data nodes were built. In order to support operations with list node elements (as single entity) 
the functionality
require to be updated (fixed).

Relatedcreated

Jira
serverONAP JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId425b2b0a-557c-3c0c-b515-579789cceedb
keyCPS-358

...

Code Block
languagejava
// before

void addChildDataNode(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String parentXpath,
        @NonNull DataNode dataNode);

void replaceDataNodeTree(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull DataNode dataNode);	

// after, alternative 1

void addChildDataNodereplaceDataNodeTree(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull String parentXpath,
        @NonNull DataNode ... dataNodedataNodes);

// after, alternative 2
void replaceDataNodeTreereplaceListDataNode(@NonNull String dataspaceName, @NonNull String anchorName, @NonNull DataNode ... dataNodeColection<DataNode> dataNodes);

Alt. 1. cons: despite usage of same methods the actual logic for processing single node significantly differs from the one 
which is required to process multiple data nodes, with taking into account the caller logic also requires update 
the as result 

  • the logic split will be required within a method itself, adding complexity to both the implementation
    and the testing
  • the invocation logic requires to be updated as well, causing extra complexity to caller logic as well

While benefit of this approach is negligible .Suggestion the suggestion is to provide separate API/SPI methods for operations with list-node elements.

Same REST API usage context

Using same REST API also seems not reasonable.

As example there is a replace (PUT) operation for a data fragment with following inputs (excluding dataspace and anchor):

  • parent node xpath
  • data fragment as JSON 
Code Block
// xpath=/test-tree
// request body:
{
	"branch": {[
        "name": "Branch",
        "nest": {
             "name": "Nest"
        } 
	]}
}

The case became uncertain because it's unclear what the action is expected exactly:

  • replace an existing data node with xpath /test-tree/branch[@name='Branch']
    or throw an exception if record with such xpath does not exist
  • replace the list node content (assumes all prior entries removal) with provided data

so there should be additional parameter to clarify which exact behavior is requested.

Any additional parameter (even optional one) leads to API/SPI for service level to be modified
in order to handle this extra parameter. It also leads to logic complication as described above.

From client perspective the additional parameter is same impact/effort as new entry point.

Suggested new entry points to be used for list-nodes only like below

/dataspaces/{dataspaceName}/anchor/{anchorName}/list-node


Implementation Proposal

Create list-node with one or more elements

Implement the functionality to support multiple nodes addition using data fragment with list-node as a root element.

REST layer (incl openapi update)

  • uri:
    • (CPS) POST /dataspaces/{dataspaceName}/anchor/{anchorName}/list-node
    •  (NCMP) POST /cm-handle/{cmHandle}/list-node
  • parameters:
    • xpath - parent node xpath (mandatory)
    • JSON data fragment via request body
  • response 201 on success

Service layer

  • parse JSON string into collection of DataNode objects

Persistence layer

  • find parent node by parent node xpath (throw not found exception if absent)
  • add all provided elements to parent node
  • persist (throw already exists exception on unique constraint violation)

Jira
serverONAP JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId425b2b0a-557c-3c0c-b515-579789cceedb
keyCPS-360

Delete list-node content (all existing elements)

Implement the functionality to support multiple nodes removal using list-node xpath.

REST layer (incl openapi update)

  • uri:
    • (CPS) DELETE /dataspaces/{dataspaceName}/anchor/{anchorName}/list-node
    •  (NCMP) DELETE /cm-handle/{cmHandle}/list-node

REST layer (DataRestController.java)

  • Implement the method deleteListNodeElements(final String dataspaceName, final String anchorName, final String listNodeXpath)
  • Call cpsDataService.deleteListNodeData()
  • return 200

REST layer (cpsData.yml)

  • Add patch

REST layer (DataRestControllerSpec.groovy)

  • Ensure appropriate REST responses on invocation 

Service layer (CpsDataService.java)

  • Create new abstract method deleteNodeTree() 

Service layer (CpsDataServiceImpl.java)

  • Override abstract method deleteNodeTree()
  • Validate the xpath of the list-nodes String
  • call cpsDataPersistenceService.deleteListDataNodes()
  • notificationService.processDataUpdatedEvent(dataspaceName, anchorName)

Service layer (CpsDataServiceImplSpec.groovy)

  • delete list-node data fragment under existing node
  • delete list-node data fragment under non existing node

Persistence layer (CpsDataPersistenceService.java)

  • Create new abstract method deleteListDataNodes()

Persistence layer (CpsDataPersistenceServiceImpl.java)

  • Override abstract method deleteListDataNodes()
  • Use method getFragmentByXpath() to get the parentEntity of the List-Node
  • Use parentEntity and a method parameter String listNodeXpath as arguments for method removeListNodeDescendants()

Persistence layer (CpsDataPersistenceServiceSpec.groovy)

  • Delete list node content successfully
  • Error thrown when listNodeXpath does not exist

Jira
serverONAP JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId425b2b0a-557c-3c0c-b515-579789cceedb
keyCPS-361

Replace list-node content

Implement the functionality to support multiple nodes replacement using data fragment with list-node as a root element.

REST layer (incl openapi update)

  • uri:
    • (CPS) PATCH /dataspaces/{dataspaceName}/anchor/{anchorName}/list-node
    •  (NCMP) PATCH /cm-handle/{cmHandle}/list-node
  • parameters:
    • xpath - parent node xpath (mandatory)
    • JSON data fragment via request body
  • response 204 on success

Service layer

  • parse JSON string into collection of DataNode objects

Persistence layer

  • extract list-node xpath identifier from data nodes provided
  • find parent node by parent node xpath (throw not found exception if absent)
  • remove all children matching (starting with) list-node xpath identifier
  • add all provided elements to parent node
  • persist

Jira
serverONAP JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId425b2b0a-557c-3c0c-b515-579789cceedb
keyCPS-362







Proposal