I'm currently having a problem with dealing with linking between two modules with different baselines.
Example:
I have a module A with 10 baselines and module B with 10 baselines.
Links are out links from A => B. The last baseline of module A has been done 1 month after the last baseline of module B. In the meantime more objects in module B have been created and were linked from module A to them.
So now I have some links in the last baseline of module A that link to objects in module B that are non existent in the last baseline of module B (only are existent in the last baseline++).
When I run my DXL-Script in order to get all linked objects I also get the IDs of these non existent object eventhough they do not exist in the last baseline. I open both modules and load the last baseline with the load(module, baseline,false) function. The name of the baseline works and my debugging shows me that I'm really working on the latest baseline. But somehow these non existent objects are listed because of the linking. I've read something about echoed links but they do not work for me.
A possible solution would be to get the Date of the baseline of module A and compare it with the creation date of the linked object. But there must be an easier and cleaner way imho... any ideas?
I am sorry that I do not have a direct answer to your question. I tried a script between two modules (A and B) like you presented. I linked the objects, made a new baseline, and added a few more objects that was also linked up.
I do not meet the problem you presented when I run the following script. I hope there could be something that gives you a new idea. Basically I open a baseline of Module B and count in-links. Newer objects (which I find in current version) are not included in this count.
Module modB = read("/Testmappe/ModuleB", false)
Module baselineModuleB
Object objB
Link l
string linkModName = "*"
int countLinks = 0
// baseline(MAJ, MIN, SUFFIX)
Baseline myBaseline = baseline(0, 1, "")
if(baselineExists(modB, myBaseline))
{
baselineModuleB = load(modB, myBaseline, false)
for objB in baselineModuleB Module do {
for l in all(objB<-linkModName) do {
countLinks++
}
}
print "Number of in-links are: " countLinks ""
}
Related
I'm trying to understand how to use knitr_out, file_out and vis_drake_graph properly in drake.
I have two questions.
Q1: Usage of knitr_out and file_out to create markdown reports
While a code like this works correctly for one of my smaller projects:
make_hyp_data_aggregated_report <- function() {
render(
input = knitr_in("rmd/hyptest-is-data-being-aggregated.Rmd"),
output_file = file_out("~/projectname/reports/01-hyp-test.html"),
quiet = TRUE
)
}
plan <- drake_plan(
...
...
hyp_data_aggregated_report = make_hyp_data_aggregated_report()
...
...
)
Exactly similar code in my large project (with ~10+ reports) doesn't work exactly right. i.e., while the reports get built, the knitr_in objects don't get displayed as the blue squares in the graph using drake::vis_drake_graph() in my large project.
Both projects use the drake::loadd(....) within the markdown to get the objects from cache.
Is there some code in vis_drake_graph that removes these squares once the graph gets busy?
Q2: file_out objects in vis_drake_graph
Is there a way to display the file_out objects themselves as circles/squares in vis_drake_graph?
Q3: packages showing up in vis_drake_graph
Is there a way to avoid vis_drake_graph from printing the packages explicitly? (Basically anything with the ::)
Q1
Every literal file path needs its own knitr_in() or file_out(). If you have one function with one knitr_in(), even if you use the function multiple times, that still only counts as one file path. I recommend writing these keywords at the plan level, e.g.
plan <- drake_plan(
r1 = render(knitr_in("report1.Rmd"), output_file = file_out("report1.html")),
r2 = render(knitr_in("report2.Rmd"), output_file = file_out("report2.html")),
r3 = render(knitr_in("report3.Rmd"), output_file = file_out("report3.html"))
)
Q2
They should appear unless you set show_output_files = FALSE in vis_drake_graph().
Q3
No, but if it's any consolation, I do regret the decision to track namespaced functions and objects at all in drake. drake's approach is fundamentally suboptimal for tracking packages, and I plan to get rid of it if there ever comes time for a round of breaking changes. Otherwise, there is no way to get rid of it except vis_drake_graph(targets_only = TRUE), which also gets rid of all the imports in the graph.
I have a SOAP node, that retrieve information from a URL in a tree structure.
Then i have a compute node to define each environment variable to each namespace variable of the SOAP retrieve.
And finally, i have a mapping node, to move the content to my message assembly structure in XML.
The error its giving me it's this (IN THE COMPUTE NODE):
I have a structure like this:
ListDocs
Description
DocType
ListTypes
Attribute
Lenght
Description
Nature
Required
ListDocs
Description
DocType
ListTypes
Attribute
Lenght
Description
Nature
Required
ListDocs
Description
DocType
ListTypes
Attribute
Lenght
Description
Nature
Required
The problem is that, when i do the definition of the variables, I do it like the code below, in the COMPUTE NODE:
WHILE I < InputRoot.SOAP.Body.ns:obterTiposDocProcessosResponse.ns:return.ns75:processo.ns75:listaTiposDocumentos
DO
SET Environment.Variables.XMLMessage.return.process.listDocs.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:description;
SET Environment.Variables.XMLMessage.return.process.listDocs.tipoDocumento = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:DocType;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.attribute = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:atribbute;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.lenght = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:lenght;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:description;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.nature = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:nature;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.required = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs.ns75:listTypes.ns75:required;
SET I = I+1;
END WHILE;
BUT, in my XML final structure, it only prints the values of my first listDocs, and i want to print all of my listDocs structures.
NOTE: WITH THE WHILE LIKE THIS, IT DOESN'T EVEN WORK. I HAVE TO REMOVE THE WHILE TO PRINT THE FIRST listDocs like i said Above.
Any help?
I NEED HELP TO LOOP THE STRUCTURES, WITH A WHILE OR SOMETHING.
You should try to use the following synthax :
DECLARE I INTEGER 1;
DECLARE J INTEGER;
J = CARDINALITY(InputRoot.SOAP.Body.ns:obterTiposDocProcessosResponse.ns:return.ns75:processo.ns75:listaTiposDocumentos[])
WHILE I <= J DO
SET Environment.Variables.XMLMessage.return.process.listDocs.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:description;
....
END WHILE;
You only missed the CARDINALITY function to get the number of elements, and also the [] to define the table, and then using this [I] while accessing the elements
Note : in my sample above, the environment will be overridden at each iteration of the loop, so only the last record will be printed. You can use the [I] in the output as well if you want to construct a table in output, or you can use the following code to push each message to the output terminal (this means you have one message in input, and 3 message coming out of the output terminal)
PROPAGATE TO TERMINAL 'Out';
So for example, based on your code, if you want to generate 3 messages based on your input containing multiple element :
DECLARE I INTEGER 1;
DECLARE J INTEGER;
J = CARDINALITY(InputRoot.SOAP.Body.ns:obterTiposDocProcessosResponse.ns:return.ns75:processo.ns75:listaTiposDocumentos[])
WHILE I <= J DO
SET Environment.Variables.XMLMessage.return.process.listDocs.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:description;
SET Environment.Variables.XMLMessage.return.process.listDocs.tipoDocumento = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:DocType;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.attribute = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:atribbute;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.lenght = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:lenght;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:description;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.nature = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:nature;
SET Environment.Variables.XMLMessage.return.process.listDocs.listTypes.required = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:required;
PROPAGATE TO TERMINAL 'Out';
END WHILE;
RETURN FALSE;
For your global information, the RETURN TRUE is the instruction "pushing" the message built in the ESQL code to the output terminal. If you use PROPAGATE instruction (same effect), you should RETURN FALSE to avoid sending an empty message after looping on your records. Another way to do it is to propagate on another terminal (i.e : 'out1'), and keep the return true. In this case, you would have all you records coming out from the out1 terminal, and a message going out of the output temrinal (due to the return true) once all the messages have been propagated (this might be useful in many situations)
So the key to understanding IIB and ESQL is that you are looking at in memory Trees built from nodes.
Each Node has pointers/REFERENCEs to PARENT, NEXTSIBLING, PREVSIBLING, FIRSTCHILD and LASTCHILD Nodes.
Nodes also have FIELDNAME, FIELDNAMESPACE, FIELDTYPE and FIELDVALUE attributes.
And last but not least that you are building Output Trees by navigating Input Trees. The Environment Tree, which you are using, is a special long lasting Tree that you can both read from and write to.
So in your code InputRoot.SOAP.Body.ns75:processo.ns75:listDocs can be thought of as shorthand for instructions to navigate to the ns75:listDocs Node. The dots '.' tell ESQL interpreter the name of the child Node of the current Node. If you were telling someone how to navigate the Nodes it would go something like this.
Start at InputRoot. InputRoot is a special Node that is automatically available to you in your ESQL Modules code.
Navigate to the first child Node of InputRoot that has the name SOAP
Navigate to the first child Node of SOAP that has the name Body
Navigate to the first child Node of Body that has the name listDocs and is in the ns75 namespace.
In the absence of a subscript ESQL assumes you want the first Node that matches the specified name ns75:listDocs and ns75:listDocs[1] both refer to the same Node.
This explains what was happening in your code. You were always navigating to the same listDocs[1] node in the InputRoot and Environment Trees.
#Jerem's code improves on what you were doing by at least navigating across the listDocs nodes in the Input tree.
For each iteration of the loop the subscript [I] gets incremented and thus it chooses a different listDocs Node. The listDocs Nodes are siblings and thus the code will access the first, second and third instance of the listDocs Nodes.
InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[1] <-- Iteration I=1
InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[2] <-- Iteration I=2
InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[3] <-- Iteration I=3
To correct #Jerem's answer you'd need to use subscripts on the lefthand side of the statement as well. Picking the description field as an example you'd need to change your code as follows.
SET Environment.Variables.XMLMessage.return.process.listDocs[I].listTypes.description = InputRoot.SOAP.Body.ns75:processo.ns75:listDocs[I].ns75:listTypes.ns75:description;
Using subscripts is regarded as a performance no no. Imagine you had 10,000 listDocs this would result in each and every iteration of the loop walking down the tree over the InputRoot, SOAP, Body, ns75:processo Nodes and then across the listDocs sibling nodes until it found the ns75:listDocs[I] Node.
This means by the time we get round to processing ns75:listDocs[10000] it will have had to repetetively walked over all the other listDocs Nodes time and time again, In fact we can calculate it would have walked over (4 x 10,000) + ((10,000 x (10,000 + 1)) / 2) = 50,045,000 Nodes
So it's REFERENCE's to the rescue and also the answer to your question. Try a loop like this.
DECLARE ns75 NAMESPACE 'http://something.or.other.from.your.wsdl';
DECLARE InListDocsRef REFERENCE TO
InputRoot.SOAP.Body.ns75:processo.ns75:listDocs;
WHILE LASTMOVE(InListDocsRef) DO
DECLARE EnvListDocsRef REFERENCE TO Environment;
CREATE LASTCHILD OF Environment.Variables.XMLMessage.return.process AS EnvListDocsRef NAME 'listDocs';
SET EnvListDocsRef.description = InListDocsRef.ns75:description;
SET EnvListDocsRef.tipoDocumento = InListDocsRef.ns75:DocType;
SET EnvListDocsRef.listTypes.attribute = InListDocsRef.ns75:listTypes.ns75:atribbute;
SET EnvListDocsRef.listTypes.lenght = InListDocsRef.ns75:listTypes.ns75:lenght;
SET EnvListDocsRef.listTypes.description = InListDocsRef.ns75:listTypes.ns75:description;
SET EnvListDocsRef.listTypes.nature = InListDocsRef.ns75:listTypes.ns75:nature;
SET EnvListDocsRef.listTypes.required = InListDocsRef.ns75:listTypes.ns75:required;
MOVE InListDocsRef NEXTSIBLING REPEAT NAME;
END WHILE;
The code above only walks over 4 + 10,000 Nodes i.e. 10 thousand Nodes vs 50 million Nodes.
A couple of other useful things to know about setting references are:
To point to the last element you can use a subscript of [<]. So to point to the last ListItem in the aggregate MyList you would code Environment.MyList.ListItem[<]
You can use an asterisk * to set a reference to an element in the tree that you don't know the name of e.g. Environment.MyAggregate.* points to the first child of MyAggregate regardless of it's name.
You can also use asterisks * to choose an element irregardless of it's namespace InListDocsRef.*:listTypes.*:description
For anonymous namespaced elements use *:* but be very careful * and *:* are not the same thing the first means no namespace any element and the second means any namespace any element.
To process lists in reverse combine the [<] subscript with the PREVIOUSSIBLING option of MOVE.
So a chunk of code for reversing a list might go something like:
DECLARE MyReverseListItemWalkingRef REFERENCE TO Environment.MyList.ListItem[<];
WHILE LASTMOVE(MyReverseListItemWalkingRef) DO
CREATE LASTCHILD OF OuputRoot.ReversedList.Item NAME 'Description' VALUE MyReverseListItemWalkingRef.Desc;
MOVE MyReverseListItemWalkingRef PREVIOUSSIBLING REPEAT NAME;
END WHILE;
Learn how to use REFERENCES they are extremely powerful and one of your simplest options when it comes to performance.
I try to use
across 1|..|list.count as j
all
list.i_th(z) ~ old list.i_th(z)
end
but it says unknown identifier z. Whats wrong with this syntax??
The syntax is correct. However, no identifier of name z is declared, hence the error. There is a cursor variable j instead. The items at the current cursor position are accessed with j.item.
Another issue is that j is evaluated in the current context (the postcondition), but old expressions are evaluated before the feature body is executed, where j is absent. As a result the code with old list.i_th (j.item) would not compile. In other words, the value should be taken from the old list but with the current index. The expression (old list).i_th (j.item) does the trick.
But this still does not do what is needed. It turns out that old list = list because the reference to the list object remains the same. To get the old elements, the copy of the list is required instead: (old list.twin).
Combining all the above, the expression should look like across 1 |..| list.count as j all list.i_th (j.item) ~ (old list.twin).i_th (j.item) end.
I'm new to Julia language and I wanted to improve my understanding by implementing a double linked list.
Unfortunately it seems that there is no good existing library for this purpose.
The only good one is the single linked list (here).
There is one implementation of a double linked list (here). But this is 2 years old and I'm not sure if it is outdated or not. And it does not allow a real empty list. It is just a single element with a default value.
At the moment I would be able to implement the common stuff like push!, pop!, that's not the problem.
But I'm struggling with implementing a double linked list that could be empty.
My current approach uses Nullable for a optional value of the reference and value.
type ListNode{T}
prev::Nullable{ListNode{T}}
next::Nullable{ListNode{T}}
value::Nullable{T}
ListNode(v) = (x=new(); x.prev=Nullable{x}; x.next=Nullable{x}; x.value=Nullable(v); x)
ListNode(p, n, v) = new(p, n, v)
end
type List{T}
node::Nullable(ListNode{T})
List() = (start=new(Nullable(ListNode{T}())); node=start; start)
List(v) = (start=new(Nullable(ListNode{T}(v))); node=start; start)
end
But it seems like this is pretty ugly and inconvenient to work with.
My second approach would be to introduce a boolean variable (inside List{T}) which stores if a list is empty or not. Checking this boolean would me allow to simply handle push! and pop! to empty lists.
I tried to google a good solution but I didn't found one.
Can anyone give me a "julia style" solution for the double linked list?
Thanks,
felix
There is now a library containing various data structures, DataStructures.jl Some initial notes regarding the question. As of this writing, type is decrepitated. Instead, mutable struct should be used, for Julia 1.0 and beyond. Nullable is also decrepitated, and a Union of Nothing and the type in question can be used instead.
There exist a package called DataStructures.jl that provides what you need.
You can find a DoubleLinked list containing the functionality you need here:
mutable_list
Code snippets from the link above, defining a DoubleLinked list in Julia >= v 1.1:
mutable struct ListNode{T}
data::T
prev::ListNode{T}
next::ListNode{T}
function ListNode{T}() where T
node = new{T}()
node.next = node
node.prev = node
return node
end
function ListNode{T}(data) where T
node = new{T}(data)
return node
end
end
mutable struct MutableLinkedList{T}
len::Int
node::ListNode{T}
function MutableLinkedList{T}() where T
l = new{T}()
l.len = 0
l.node = ListNode{T}()
l.node.next = l.node
l.node.prev = l.node
return l
end
end
In addition to the DataStructures package, Chris Rackauckas' LinkedLists.jl is a good resource.
The source code is quite readable and you can always ask questions.
I have gone through msdn article, read whitepaper on number sequences and made number sequences a lot many times. But in this scenario I need some help.
Scenario is; I want to get next sequence number through x++ code using just number sequence code and no reference etc.
I have tried following (and many others but this is nearest solution) ;
static void myTestJob(Args _args)
{
NumberSeq num;
num = NumberSeq::newGetNumFromCode('SAO-Y');
info(num.num()) ;
}
It generates number sequence against some number sequence codes, but for other it throws error that;
"Number sequence does not exist."
I have tried many other options mentioned on many other blogs and tried to explore AX as well, but now need some assistance.
P.S. I'm not creating number sequence using x++ code but from front end (organization administration).
I am able to suppress the exception by using following;
num = NumberSeq::newGetNumFromCode(<<someNumberSequenceCode>>, NumberSeqScopeFactory::createDefaultScope(), true, true);
As, fourth optional parameter of NumberSeq::newGetNumFromCode(,,,true); says not to throw exception on missing reference.
boolean _dontThrowOnMissingRefSetUp = false,
As I said earlier, I have created number sequence from organization administration without writing any code (EDT, class, parameters table etc. stuff) so no reference was generated and I think I was getting exception due to this.
Please have a look at your number sequence that you have set up. I recon it has something to do with the numbersequence scope.
Make sure the scope of the number sequence is valid within the company you are calling this.
It's work, but not raice result: Voucher not generated.
Working way:
num = NumberSeq::newGetNumFromCode(<<someNumberSequenceCode>>,
NumberSeqScopeFactory::createDefaultScope(), **false**, true);
When my Number Sequence - Scope is setup as Shared I can use this code:
numSequence = NumberSeq::newGetNumFromCode(<<someNumberSequenceCode>>, NumberSeqScopeFactory::createDataAreaScope(curext()), true, true);
When my Number Sequence - Scope is setup as Company I can use this code:
numSequence = NumberSeq::newGetNumFromCode(<<someNumberSequenceCode>>);