Add an Object in the namespace with a "AddIn" reference - node-opcua

I am using node-opcua to create an OPC UA Server. The nodeset of the companion specification that i am working with dictates an "AddIn" Reference.
Is it possible to add an Object to the namespace that is referenced as hasAddIn by it's parent object?
There is no property like "addInOf" within AddObjectTypeOptions such as "componentOf".
To add components to an object I use
const _Identification = namespace.addObject({
componentOf: myMachine,
browseName: "Identification",
typeDefinition: baseObjectType.getChildByName('FolderType').getChildByName('FunctionalGroupType').getChildByName('MachineIdentificationType').getChildByName('MachineToolIdentificationType')
});
Alternatively I thought of creating the object as a component first and change the reference afterwards but I dind't find a suitable method.

To add the HasAddIn reference between nodes, you can make use of the references property of the AddBaseNodeOptions interface. It is of type AddReferenceOpts.
To add AddIn reference to object,
const _Identification = namespace.addObject({
browseName: "Identification",
references: [{
referenceType: "HasAddIn",
nodeId: <provide the nodeId of the AddIn here>
}]
});
Hope this answers your question.

Related

API reference: Where to find all the properties available for aggregation binding info object?

Where can I find aggregation binding properties like path, factory, etc.. in the API reference?
Just like in following code
<List items="{
path: '/Products',
factory: '.productListFactory',
...
}">
Where to find more such properties and their descriptions?
You can see more such properties in ManagedObject#bindAggregation.
Additionally, parameters and events await key-value pairs of which the possible keys are documented in the corresponding model type.
For example, the keys for parameters, when binding with a v2.ODataModel, can be found in ODataModel#bindList or in ODataListBinding. The latter module also documents which events can be registered.
{ // Standard options. See ManagedObject bindAggregation
path: '...',
filters: [/*...*/],
...
parameters: { // Model dependent. See e.g. ODataListBinding constructor
expand: 'ToA, ToB/ToB1/ToB2, ToC',
select: 'ProductID, ProductName',
custom: 'myCustomQuery',
batchGroupId: 'myGroup',
},
events: { // Model dependent. See e.g. ODataListBinding events
dataRequested: '.onDataRequested',
dataRequested: '.onDataReceived',
change: '.onDataChange'
}
}
That's a binding (they're enclosed in {}).
You can use the getBindingInfo method.
So, for example, if your List control has the id "mylist":
this.getView().byId("mylist").getBindingInfo("items");
It will return you an object containing all the binding properties, such as path and factory.

How to pass Category Attribute value from REST API

I am able to upload files or create node through the Content server(16.0.3) REST Api (POST: api/v1/nodes).
But How do I pass Category Attribute value while uploading file to opentext Content server..
Because as per DeveloperGuide there are only 3 parameters that I can pass
type,parent_id,name
To add a category to node, need to pass roles with Category, Category Attribute values in Json formate.For example node (20589) has category with name BillingCat(42069) contains ReferenceID (42069_2) then pass parameters as below
type: 144,
parent_id: 20589,
name: file.name,
roles: {
categories: {
{
'42069': { // category (42069)
'42069_2': 'ABC23' //attribute value
}
}
}
Looks like you have to make a second post after node has been created:
POST api/v1/nodes/{id}/categories
Hope this helps

Apigility: How to render embedded objects?

How do I render embedded objects in Apigility? For example, if I have a 'user' object and it composes a 'country' object, should I be rendering the 'country' object as an embedded object? And how should I do this?
I am using the Zend\Stdlib\Hydrator\ArraySerializable. My getArrayCopy() method simply returns an array of properties that I want exposed. The array keys are the property names. The array values are the property values. In the case of user->country, the value is an object, not a scalar.
When I return the user object from UserResource->fetch(), here's how it is rendered:
{
"id": "1",
"firstName": "Joe",
"lastName": "Bloggs",
"status": "Active",
"email": "test#example.com",
"country": {
"code": "AU",
"name": "Australia"
},
"settings": "0",
"_links": {
"self": {
"href": "http://api.mydomain.local/users/1"
}
}
}
Note that 'country' is not in an _embedded field. If it is supposed to be in _embedded, I would have thought that Apigility would automatically do that (since it automatically adds the _links object).
As a related issue, how do I go about returning other rel links, such as back, forward, etc?
The easiest way to get Apigility to render embedded resources is when there is an API/resource associated to the embedded object. What I mean for your example is that you'd have an API resource that has a country entity. In that case, if your getArrayCopy returned the the CountryEntity, Apigility would render it automatically as an embedded resource.
If your getArrayCopy is returning country as an array with code and name, you'll end up with what you saw.
For the other part, the rel links for first, last, prev and next will come from the fetchAll method when you return a Paginator. Your collection extends from this already, but it needs an adapter. The code could look something like this:
public function fetchAll($params)
{
// Return a \Zend\Db\Select object that will retrieve the
// stuff you want from the database
$select = $this->service->fetchAll($params);
$entityClass = $this->getEntityClass();
$entity = new $entityClass();
$hydrator = new \Zend\Stdlib\ArraySerializable();
$prototype = new \Zend\Db\ResultSet\HydratingResultSet($hydrator, $entity);
$paginator = new \Zend\Paginator\Adapter\DbSelect($select, $this->sql, $prototype);
$collectionClass = $this->getCollectionClass();
return new $collectionClass($paginator);
}
There are other paginator adapters as well - an ArrayAdapter which will take in an array of however big and then paginate it so you only get the desired number of results. The downside to this if you use it with database results, you'll potentially be retrieving and discarding a lot of results. The DbSelect paginator will modify the $select object to add the limit and order clause automatically so you only retrieve the bits you need. There are also adapters if you're using DbTableGateway, Iterators or even callbacks. You can also implement your own of course.
Hope this helps. If you have more specific needs or clarification, please comment and I'll do my best.
I posted this example on github.
https://github.com/martins-smb/apigility-renderCollection-example
Hope this helps.

breeze metadata when multiple types has/share the same short name

I generate the metadata from the database following the http://www.breezejs.com/documentation/load-metadata-script
My question is : How can I generate the metadata for two entities that has the same name but a different shema in the database ?
I tried to use a qualified name for my entities like this : ...
"entityType": [
{
"name": "Admin.RefactorColumn",
"key": {
"propertyRef": {
"name": "Id"
}
},
"property": [
{
"name": "Id",
"type": "Edm.Int32",
"nullable": "false",
"annotation:StoreGeneratedPattern": "Identity"
}, ...
...
the problem is that when I make entityManager.saveChanges() and return the saveResult(also made by hand) from server breeze look for an entity with the name RefactorColumn:#Admin ... instead of Admin.RefactorColumn:#...
I have no issue if name is just "RefactorColumn" instead of "Admin.RefactorColumn"
Can I solve this issue changing the metadata format or the saveResult format ?
Thank for any help !
All breeze EntityTypes have a concept of a namespace qualified name. This name is a composition of a 'shortName' and a 'namespace'. As of breeze 1.4.16 a qualified name can be created by calling the EntityType.qualifyTypeName static function. i.e.
var shortName = "Employee";
var namespace = "My.Qualified.Namespace";
var qualifiedName = breeze.EntityType.qualifyTypeName(shortName, namespace);
// qualifiedTypeName will be => "Employee:#My.Qualified.Namespace"
In general, all breeze APIs will accept either a shortName OR a qualified name. If a shortName is provided then breeze will internally convert it to a qualified name by finding the first qualified name within the local metadataStore with a matching shortName.
Breeze metadata for each entity type can either be retrieved from a server or defined on the client. If defined on the client your entityType would be defined something like this:
myMetadataStore.addEntityType({
shortName: "RefactorColumn",
namespace: "Admin",
autoGeneratedKeyType: breeze.AutoGeneratedKeyType.Identity,
dataProperties: {
id: { dataType: DataType.Int32, isPartOfKey: true, isNullable: false },
// additional properties here:
},
});
There are several examples of this technique in the DocCode sample in the breeze.js.samples GitHub repo.
Alternatively, if you are defining metadata by returning json from the server you have two options, you can either return a valid OData metadata definition ( which it appears to be what you are trying to return above) OR you can use breeze's native metadata format, which is MUCH simpler. The simplest way to see what this would look like is to create the metadata on the client as shown above and the call
var exportedMetadata = myMetadataStore.exportMetadata();
The contents of the exportedMetadata will be in 'native' breeze metadata format, which is basically just a jsonified version of the internal entityType definition.

Swagger response class Map

I have a REST API that returns, essentially a Map of (String, Object) where Object is either
A custom bean (let's say class Bean) or
A List of elements, all of type Bean
In JSON, this translates very well to:
{
"key1":{
"val1":"some string",
"val2":"some other string",
"val3":"another string"
},
"key2":[
{
"val1":"some string",
"val2":"some other string",
"val3":"another string"
},
{
"val1":"some string",
"val2":"some other string",
"val3":"another string"
}
]
}
Via swagger annotations, is there a way to specify this kind of a dynamic Map as the response class?
Thanks
I read the 'Open API Specification' - 'Add support for Map data types #38' page. As far as I understand, it recommends to use additionalProperties, but I haven't managed to make it work with Swagger UI 2.1.4 (see my related question: Swagger: map of string, Object).
I have found the following work-around: define an object, with one property that is the key, and with an inner object as the value for the "key" property.
The display in Swagger UI is correct, but one does not see it is a map, so it is then needed to explain in the comment that this is actually a map.
In your case, I find it a bit weird to have once a Bean, and once a list of Beans: I would find it more logical to have an array of one Bean in the first case.
Still, you could do, for example:
your_property: {
description: "This is a map that can contain several objects indexed by different keys. The value can be either a Bean or a list of Beans.",
type: object,
properties: {
key_for_single_bean: {
description: "The value associated to 'key_for_single_bean' is a single Bean",
$ref: "#/definitions/Bean"
},
key_for_list_of_beans: {
description: "The value associated to 'key_for_list_of_beans' is an array of Beans",
type: array,
items: {$ref: "#/definitions/Bean"}
}
}
}