Acumatica foreach best practice - acumatica

I want to foreach item in SOLine. I should use
PXSelectBase<SOLine> lines = new PXSelect<SOLine, Where<SOLine.orderNbr,Equal<Required<SOLine.orderNbr>>>>(graph);
foreach (SOLine item in lines.Select(order.OrderNbr)) {}
Or
List<SOLine> lines = PXSelect<SOLine, Where<SOLine.orderNbr, Equal<Required<SOLine.orderNbr>>>>.Select(graph, order.OrderNbr).FirstTableItems.ToList();
foreach (SOLine item in lines) {}
I don't know which is better. Sorry for my English.

I would prefer the first sample, yet mostly for aestetical reasons:
It looks easier to read and understand (there's a query in line 1 and next it's executed on database with special parameter)
This code does not allocate a List< SOLine> instance that we won't need again later and it won't allocate memory to keep all the rows there, thus asking the CLR only as much memory as a single row takes.

There isn't any important difference between the two approaches shown in your examples, aside from that the one with FirstTableItems makes you do a couple extra steps - at least invoke this property itself.
I'd recommend to use the first approach with pure Select(..) because it is more succinct and does the same thing. FirstTableItems would just cast the items of the result set to the type of the first item and provide you with the typed enumerable (IEnumerable<SOLine> in your case), but because you do foreach over the items casting can be done implicitly - like in your first example. So, better use the simpler option.

Related

Having some problems with creating special type objects for groovy

When you start to use gpath processing for collections in groovy, exactly what type of data structure you are dealing with can get somewhat confusing (at least for me)--typically in groovy you just use "Duck typing" and everything works, but Duck Typing actually harms the coders understanding of what a variable might contain at any point in time.
In order to keep it straight I started breaking out variables as types to improve understanding. The types however are very cryptic and unhelpful:
Map<String, List<Map<String, String>>>
is actually a pretty common (and immensely useful) intermediate structure, but someone looking at that in code isn't really helped. (It acts much like an indexed/grouped sql table if it's not obvious, which I bet it's not)
While explaining my code to a co-worker (and trying to understand it myself) I created a few new types that more clearly state my intentions:
class Row extends LinkedHashMap<String, String>{} // Record--like a row in a table
class Table extends ArrayList<Row>{} // A table--like an SQL table. A list of rows
class GroupedTable extends LinkedHashMap<String, Table> // A map of tables indexed by some name using groupBy()
This works surprisingly well. After defining these I could say things like:
Table t=sql.rows(someQuery) as Table
Row r=t.get(0)
GroupedTable grouped= t.groupBy{it.an_sql_column} as GroupedTable
Sometimes I don't have to manually coerce the values (as in the Row) sometimes I do (as in the GroupedTable) which is a little confusing but it generally works (even with #TypeChecked turned on)
The biggest confusion I'm having is that even though grouped was "Converted" to GroupedTable, this closure signature doesn't work:
grouped.collect{String modelName, Table subTable->…}
It will break at runtime because even though I converted the grouped object using "as GroupedTable", it didn't convert the values returned from groupBy from LinkedLists to a tables.
It works if I use the closure signature:
grouped.collect{String modelName, LinkedList subTable->…}
but everywhere else things seem to automatically convert nicely. I tried to specify ", subTable as Table" but that is not valid syntax for a closure.
So I'm wondering if there is a way to either supply an "Automatic" conversion from LinkedList to table or to easily process a GroupedTable so that it contains Tables for it's values instead of LinkedLists
A small set of automatic conversions that made Row, Table and GroupedTable work more smoothly would be my ideal solution, but I don't think that asType() is going to do it since I'd need to apply that to LinkedList instead of Table (and it would probably require explicit "as" conversion anyway.)
Update--I just made a "fix" method in GroupedTable that seems to fix the problem but is clunky!
def fix(){keyset().each{put(it, get(it) as Table)}}
I don't know why auto-type conversion does not work
however, you could #Override the groupBymethod like this:
(Edit by billk--this is how I implemented Daggett's suggestion)
class Table extends ArrayList<Row> {
GroupedTable groupBy(Closure closure)
def gt=DefaultGroovyMethods.groupBy(this as Iterable, closure) as GroupedTable
gt.changeTypeOfAllValuesToTable()
return gt
static Table build(Iterable list){
return list.collect{it as Row} as Table
}
}
class GroupedTable extends LinkedHashMap<String, Table> {
GroupedTable changeTypeOfAllValuesToTable()
this.keySet().each{String k->
Table t=Table.build(get(k))
put(k, t)
return this
}
With a little extra effort (I could post it if anyone is interested) I got these all to work with the #TypeChecked annotation. I will probably clean these up and make more useful classes out of them.

How to refer to alternate resources in Terraform?

Terraform (as of today) has the somewhat disturbing limitation, that you cannot create a resource with an interpolated (calcuted) lifecycle attribute prevent_destroy.
Terraform: How to get a boolean from interpolation?
https://github.com/hashicorp/terraform/issues/3116
The work-around is pretty simple to code, just create 2 resources with "alternating" counts. When you have 1 "production" resource which does not allow destroying you have 0 "testing" resources which can be destroyed. Or the other way round. (See the answer to the stackoverflow question linked
above for details.)
However, this brings up a new question. When I want to refer to "the one of the alternate resources that exists for this execution", how do I do that?
In pseudo code something like
"${local.production ? "${aws_eip.commander_production.public_ip}" : "${aws_eip.commander_testing.public_ip}" }"
This pseudo code cannot work for a couple of reasons:
aws_eip.commander_production is no longer a single resource, it is a list, so you need the * syntax
one of the lists is always empty and Terraform easily complains that it cannot determine the type of an empty list. (I guess because the ternary operator requires that the alternates have the same type)
when you access into an empty list you will get an error (With C semantics the unused alternate would not be evaluated, but Terraform seems to work differently and I got errors when trying to code this)
To work around those I came up with the following hacky solution:
Extend the lists with a dummy element in the end and then refer to the
first element of the extended list. The code for this is pretty
horrible to type, but it seems to work
locals {
dummy = [ "foo" ]
}
output "0101: address" {
value = "${format("Public IP is %s", "${local.production ? "${element("${concat("${aws_eip.commander_production.*.public_ip}", "${local.dummy}")}", 0)}" : "${element("${concat("${aws_eip.commander_testing.*.public_ip}", "${local.dummy}")}", 0)}" }")}"
}
Question: What is a shorter / more elegant way to code this?
Note: I have found one answer myself, but feel welcome to contribute even better ones.
A bit shorter code is
output "0101: address" {
value = "${format("Public IP is %s", "${element("${concat("${aws_eip.commander_production.*.public_ip}", "${aws_eip.commander_testing.*.public_ip}")}", 0)}")}"
}
In plain text: Concatenate the lists and take the first element of the the result. One list has one element and the other one zero, so the result will be what we want, regardless whether the element is in the first or second list.

How to avoid creating objects to check or get content from Maps in Java

I am implementing my own Map in Java, using a custom class I made.
I already implemented the hashCode and equals without any problem.
I just have a question more related into performance and stuff like that.
So I will check many times in my application if a specific value is inside the map, for that, for that I have to create a object and then use the methods containsKey of Map.
My question is...
Is there any other way? without being always creating the object???
I cant have all the objects in my context universe, so that isn't a way...
I know I can just point the object to 'null' after using it, but still, it's not so elegant, creating objects just to check if there is the same object inside =S
Are there any other conventions?
Thank you very much in advance!
EDIT:
Stuff typed = new Stuff(stuff1, stuff2, (char) stuff3);
if(StuffWarehouse.containsKey(typed))
{
//do stuff
}
//after this I won't want to use that object again so...
typed = null;

Remove Single Metaclass Method

I've been starting to learn Groovy and am currently looking at the metaclass functionality. I have seen the examples of adding a new method, and removing all methods, but nothing about removing a single method. For example:
String.metaClass.foo = {delegate.toUpperCase()}
String.metaClass.bar = {delegate.toLowerCase()}
with the obvious side-effects. Now I have seen that you can say
String.metaClass = null
To remove all of the methods. I would expect one could say something along the lines of
String.metaClass.foo = null
to remove String.foo(), but have String.bar() remain, however this statement does not seem to have any effect. Is there a way to say method foo() should no longer be defined, without effecting bar() or any other added methods?
If you search this webpage for "remove method" it says that you should be able to remove a method using the exact syntax you've proposed above. But I tested it, and you're right, it doesn't seem to work.
A workaround is to assign a closure that throws MissingMethodException, which is what happens by default when you call a method that doesn't exist, e.g.
// Add method
String.metaClass.foo = {delegate.toUpperCase()}
// Remove method
def removeMethod = {throw new MissingMethodException()}
String.metaClass.foo = removeMethod
Admittedly, this is not the most pleasing solution.
As a followup, I posted a bug report here:
https://issues.apache.org/jira/browse/GROOVY-4189
And the documentation has been changed now
See the bug report for the reason this was never implemented
Don's answer is the best way around this

IDynamicObject implementation ignores multiple property invocations

I've implemented IDynamicObject in C# 4, return a custom MetaObject subclass that does simple property getter/setter dispatch to a Dictionary. Not rocket science.
If I do this:
dynamic foo = new DynamicFoo();
foo.Name = "Joe";
foo.Name = "Fred";
Console.WriteLine(foo.Name);
Then 'Joe' is printed to the console... the second call to the 'Name' setter is never invoked (never steps into my custom dispatcher code at all).
I know the DLR does callsite caching, but I assumed that wouldn't apply here. Anyone know what's going on?
Whatever MetaObject you're returning from (Bind)SetMember will be cached and re-used in this case. You have 2 dynamic sites doing sets. The 1st call will cache the result in an L2 cache which the 2nd site will pick up before asking you to produce a new rule.
So whatever MetaObject you're returning needs to include an expression tree that will update the value. For example it should do something like:
return new MetaObject(
Expression.AssignProperty(this.Expression, value.Expression),
Restrictions.TypeRestriction(this.Expression, this.Value.GetType());

Resources