Recursion error while creating Asset which is having self-join relationship - hyperledger-composer

I have defined Asset as :
asset PurchaseOrderAsset identified by orderId {
o String orderId
--> SupplierChainParticipant createdBy
--> SupplierChainParticipant assignedTo
o String description
o String status
o Integer quantity
o String assetId
o PurchaseOrderAsset[] subPurchaseOrders
}
Now, When I am trying to create Asset, I am getting error as "InternalError: too much recursion". i am facing this error in composer playground.
Can we have self-join relationship or not?

This is a bug, please create an issue for it, attaching your example BNA.
To workaround it I recommend that you create a concept for the line items of a purchase order. Conceptually those "sub" purchase orders are not assets, because they are not addressable through a registry.
Please also see: Different between 'o' and arrow symbol used in .cto file?

Related

Reference in modeling language

This will not create a reference loop in modeling language, right?
participant Owner identified by name {
o String name
o Car[] cars
}
asset Car identified by plateNumber {
o String plateNumber
--> Owner owner
}
Correct - it won't. Your model simply creates an array of cars in participant class Owner and a relationship (identifier) to owner from the asset class Car. This is perfectly fine and reasonable as for as modeling goes and the circular nature of what you're asking.

How to extend multiple classes in Hyperledger composer .cto file

I want to create a new Role extending two existing roles. So is it possible in composer modelling language for a participant to extend multiple participants?
It is not likely to be supported as multiple inheritance is tricky and you would be forced into design issues in Object Oriented systems - Diamond Problem in multiple inheritance .
A Participant Type can only Extend one Participant type.
Using Concepts may allow you "re-use" elements of the model and ensure consistency.
concept Manager {
o String MTitle
o String QualificationType
}
concept Engineer {
o String ETitle
o String CharterCertType
}
participant Mgr identified by mID {
o String mID
o String name
o Manager manager
}
participant Engr identified by eID {
o String eID
o String name
o Engineer engineer
}
participant EMgr identified by emID {
o String emID
o String name
o Manager manager
o Engineer engineer
}
The modelling language is covered in Modelling Language and Model Compatibility

Composer query to match a participant reference

So I have a query like this:
query selectOrder{
description: "Select an Order that matches a Client reference and an Order Number"
statement:
SELECT com.x.Order
WHERE (client == _$client AND orderNumber == _$orderNumber)
}
The order is something like this:
asset Order identified by uuid {
o String uuid
--> Client client
o String orderNumber
--> Item[] items
}
How do I pass the reference to the client to the query?
I tried the reference and was told to toJSON it.
I tried that and it won't parse the thing - there's a clear issue with the parsing of the query.
I can't find the answer in the docs, so I'm wondering if anyone has done this or if I have to save the client id instead of the reference to client and lose the integrity.
EDIT: For completeness for the first answer below.
I'm trying to add an Item to the array of Items.
My Item object is defined like this:
asset Item identified by uuid {
o String uuid
o DateTime timestamp
o String orderNumber
--> Client client
o String[] message
}
When the transaction is invoked the single object passed in is the Item.
I'm setting Item.client as the _$client value in the query.
Should I be pre-pending it with "resource:"?
I'm asking because I thought that was in the reference string already - at least it is in the view in the playground.
EDIT2:
So I manually construct the following variable:
var RSRC = 'resource:com.x.Client#XYZ123'
Set that as the client in this query
return query('selectOrder', {agency : RSRC, orderNumber : orderNumber});
But I'm still getting this:
Error: unknown operator "0" - should be one of $eq, $lte, $lt, $gt,
$gte, $exists, $ne, $in, $nin, $size, $mod, $regex, $elemMatch, $type
or $all
What next?
Embedding the "resource..." string in quotes didn't work either.
Your query looks ok, but you need to pass a string with the format:
resource:type.Name#instance for the relationship.
E.g. resource:org.acme.Car#123ABC

With the use of Apex code, how can I select all ''OpportunityProducts' objects which are belongs to particular 'Opportunity Id'

I am way to customizing 'Sales' application that belongs to 'salesforce.com' platform.
Is there any way to select all the 'OpportunityProducts' objects which are belongs to particular 'Opportunity Id' ?
[SELECT Id FROM OpportunityProduct WHERE Opportunity =:opportunitId];
When I execute above code for select those 'OpportunityProduct', I got following error. If any one have some idea please update me. Thanks.
Save error: sObject type 'OpportunityProduct' is not supported. If you are attempting to use a custom object, be sure to append the '__c' after the entity name. Please reference your WSDL or the describe call for the appropriate names.
Another way to get this done when you need the actual products, not just the line items, is as follows. First get your opportunities:
List<Opportunity> opps = [SELECT Id, Name FROM Opportunity LIMIT 1000];
Then loop through to create a list of opportunity Ids
List<Id> oppIds = new List<Id>();
for(Opportunity o : opps)
{
oppIds.add(o.Id);
}
Now get your actual products that belong to your opportunities...
List<OpportunityLineItem> oppProds = [SELECT Id, PricebookEntry.Product2.Name, PricebookEntry.Product2.Family
FROM OpportunityLineItem
WHERE OpportunityId IN :oppIds];
Hope that helps.

Linq: Polymophic entity fetch in select list

I want to do the following...
FROM o IN orders
SELECT new OrderContainer { Contact = (PostalContact) o.Contact }
So hopefully you can see that the order's 'Contact' will be of a derived type. Unfortunately however it doesn't seem to do a polymorphic fetch! Is there anyway of achieving this?
Cheers, Ian.
Try using the extention method .OfType()
from o in orders
select new OrderContainer { Contact = o.Contact.OfType<PostalContact>().FirstOrDefault() }
Edit:
a way to get the full object data, but i doubt that this is good enough for your needs.
from c in contacts.OfType<PostalContact>()
where c.Orders.Any(o=>o.Contact.Id == c.id)
select new OrderContainer { Contact = c }
on the other hand, if you set the base class (entity) to abstract, you may find that entity will load the full objects. but this is not recomended due to the queries that are generated. if you are looking into this you may want to look at (TPH) Table per Hierarchy for your contacts

Resources