Including the max and offset criteria inside GORM criteriaBuilder returns an error - grails

Can I make this code shorter?
if(count == null && from = null) {
creditAdviceList = CreditAdvice.findAll {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
}
else if(count != null && from == null) {
creditAdviceList = CreditAdvice.findAll(max: count) {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
}
else if(count == null && from != null) {
creditAdviceList = CreditAdvice.findAll(offset: from) {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
}
else if(count != null && from != null) {
creditAdviceList = CreditAdvice.findAll(max: count, offset: from) {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
}
You see, its a series if statement for each possible scenario. Imagine if one would to use also order and cache in the parameter- there will be basically 16 unique if statements!
I've tried this [more] shorter code:
creditAdviceList = CreditAdvice.findAll {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
if(count != null) {
maxResults(count)
}
if(from != null) {
firstResult(from)
}
}
But it gives me an error:
...No signature of method: grails.gorm.DetachedCriteria.maxResults() is applicable for argument types: (java.lang.Integer)...
I tried to convert offset to int, Integer, String, etc. I also omit the if statement inside the criteria, but the same error message occur.

findAll with a closure passed is using a DetachedCriteria internally, which is not the same as the result you would get from createCriteria mentioned in the docs. If groovy would find "something close" enough, it would tell you in the error message. The easiest way to deal with your max/from demands would be with simply with a map (which is the first argument passed). E.g.:
def qcfg = [:]
if (count) {
qcfg.count = count
}
if (from) {
qcfg.offset = from
}
creditAdviceList = CreditAdvice.findAll(qcfg) { ... }
mix, match, extract, shorten as you see fit

As far as I see, the only difference is the pagination options. If my eyes are not tricking me, yes, you can:
Map paginationArgs = [max: count, offset: from].findAll {
it.value != null
}
List<CreditAdvice> creditAdviceList = CreditAdvice.findAll(paginationArgs) {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
You can style it differently, but basically you can build the pagination arguments first, and pass them to the findAll. No duplicated code, clearer responsability of the conditions. To clarify, I'm adding all the options and then filtering them to exclude the ones that are null.

Related

OrderClosePrice returns a price different from the history pool

When closing a (selected) existing order with the api, and in that moment I try to get the closing price, sometimes (Perhaps one out of ten times) returns a price diferent from the one I can see in the history pool.
The code is something like this:
RefreshRates();
if(type == OP_BUY)
{
currentPrice = NormalizeDouble(MarketInfo(symbol, MODE_ASK), vdigits);
}
else if(type == OP_SELL)
{
currentPrice = NormalizeDouble(MarketInfo(symbol, MODE_BID), vdigits);
}
if (meetsRequirementsToClose(currentPrice))
{
desiredPrice = currentPrice;
// And then....
bool retVal = OrderClose(OrderTicket(), numLots, desiredPrice, currSlippage);
if (retVal)
{
this.reportClosePrice (myOrderId, OrderClosePrice(), desiredPrice, numLots, "closing");
return true;
}
}
The order was previously selected using SELECT_BY_POS in the pool MODE_TRADES.
anyone knows how to fix it?
Edited:
We have a broker that sometimes respects the requested price... sometimes not.
Disregarding the fact that we have to change broker for a more reliable one, we cannot rely on the requested price.
The deviation we see is greater than one hundred points, both for better and for worse prices than the real ones.
As sugested by #TheLastStark, the problem is solved selecting the order by its ticket just before closing.
The final code is something like:
RefreshRates();
if(type == OP_BUY)
{
currentPrice = NormalizeDouble(MarketInfo(symbol, MODE_ASK), vdigits);
}
else if(type == OP_SELL)
{
currentPrice = NormalizeDouble(MarketInfo(symbol, MODE_BID), vdigits);
}
if (meetsRequirementsToClose(currentPrice))
{
desiredPrice = currentPrice;
// And then....
int tickNum = OrderTicket();
bool retVal = OrderClose(OrderTicket(), numLots, desiredPrice, currSlippage);
if (retVal)
{
if (OrderSelect(tickNum,SELECT_BY_TICKET,MODE_HISTORY)== false)
{
//this.logger.error ("Error selecting the order");
this.reportClosePrice (myOrderId, -1, desiredPrice, numLots, "closing");
}
else
{
this.reportClosePrice (myOrderId, OrderClosePrice(), desiredPrice, numLots, "closing");
}
return true;
}
}

Criteria in grails

Could you tell me what's wrong in my Criteria here?
def users
def u = User.createCriteria()
users = u.list (max: max, offset: offset) {
eq("account",account)
and {
if(teacherName != null && teacherName != ""){
like("userName", "%"+teacherName+"%")
}
if(mobileNumber != null && mobileNumber != ""){
like("mobileNumber", "%"+mobileNumber+"%")
}
eq("status", Status.ACTIVE)
eq("userType","Account Teacher")
}
}
return users
}
the list returned empty why?
The code you posted is unnecessarily verbose. An equivalent implementation is:
def users = User.withCriteria(max: max, offset: offset) {
eq("account", account)
if (teacherName) {
like("userName", "%${teacherName}%")
}
if (mobileNumber) {
like("mobileNumber", "%${mobileNumber}%")
}
eq("status", Status.ACTIVE)
eq("userType", "Account Teacher")
}
I can't say why this isn't working because I don't know what the User domain class looks like or what behaviour the query is supposed to exhibit, but it ought to be easier to debug a more concise implementation.

An exception of type 'System.OutOfMemoryException' occurred in itextsharp.dll but was not handled in user code

I am using iTextSharp to create pdf. I have 100k records, but I am getting following exception:
An exception of type 'System.OutOfMemoryException' occurred in
itextsharp.dll but was not handled in user code At the line:
bodyTable.AddCell(currentProperty.GetValue(lst, null).ToString());
Code is:
var doc = new Document(pageSize);
PdfWriter.GetInstance(doc, stream);
doc.Open();
//Get exportable count
int columns = 0;
Type currentType = list[0].GetType();
//PREPARE HEADER
//foreach visible columns check if current object has proerpty
//else search in inner properties
foreach (var visibleColumn in visibleColumns)
{
if (currentType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key) != null)
{
columns++;
}
else
{
//check child property objects
var childProperties = currentType.GetProperties();
foreach (var prop in childProperties)
{
if (prop.PropertyType.BaseType == typeof(BaseEntity))
{
if (prop.PropertyType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key) != null)
{
columns++;
break;
}
}
}
}
}
//header
var headerTable = new PdfPTable(columns);
headerTable.WidthPercentage = 100f;
foreach (var visibleColumn in visibleColumns)
{
if (currentType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key) != null)
{
//headerTable.AddCell(prop.Name);
headerTable.AddCell(visibleColumn.Value);
}
else
{
//check child property objects
var childProperties = currentType.GetProperties();
foreach (var prop in childProperties)
{
if (prop.PropertyType.BaseType == typeof(BaseEntity))
{
if (prop.PropertyType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key) != null)
{
//headerTable.AddCell(prop.Name);
headerTable.AddCell(visibleColumn.Value);
break;
}
}
}
}
}
doc.Add(headerTable);
var bodyTable = new PdfPTable(columns);
bodyTable.Complete = false;
bodyTable.WidthPercentage = 100f;
//PREPARE DATA
foreach (var lst in list)
{
int col = 1;
foreach (var visibleColumn in visibleColumns)
{
var currentProperty = currentType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key);
if (currentProperty != null)
{
if (currentProperty.GetValue(lst, null) != null)
bodyTable.AddCell(currentProperty.GetValue(lst, null).ToString());
else
bodyTable.AddCell(string.Empty);
col++;
}
else
{
//check child property objects
var childProperties = currentType.GetProperties().Where(p => p.PropertyType.BaseType == typeof(BaseEntity));
foreach (var prop in childProperties)
{
currentProperty = prop.PropertyType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key);
if (currentProperty != null)
{
var currentPropertyObjectValue = prop.GetValue(lst, null);
if (currentPropertyObjectValue != null)
{
bodyTable.AddCell(currentProperty.GetValue(currentPropertyObjectValue, null).ToString());
}
else
{
bodyTable.AddCell(string.Empty);
}
break;
}
}
}
}
}
doc.Add(bodyTable);
doc.Close();
A back of the envelope computation of the memory requirements given the data you provided for memory consumption gives 100000 * 40 * (2*20+4) = 167MBs. Well within your memory limit, but it is just a lower bound. I imagine each Cell object is pretty big. If each cell would have a 512 byte overhead you could be well looking at 2GB taken. I reckon it might be even more, as PDF is a complex beast.
So you might realistically be looking at a situation where you are actually running out of memory. If not your computers, then at least the bit C# has set aside for its own thing.
I would do one thing first - check memory consumption like here. You might even do well to try with 10, 100, 1000, 10000, 100000 rows and see up until what number of rows the program works.
You could perhaps try a different thing altogether. If you're trying to print a nicely formatted table with a lot of data, perhaps you could output an HTML document, which can be done incrementally and which you can do by just writing stuff to a file, rather than using a third party library. You can then "print" that HTML document to PDF. StackOverflow to the rescue again with this problem.

If statement not calling all methods returning BOOL

I have code like this:
-(IBAction)send {
if ([self isCorrect1] && [self isCorrect2] && ...) {
[self sendRequest];
}
}
-(BOOL)isCorrect1 {
...
}
-(BOOL)isCorrect2 {
...
}
Every isCorrect method is checking some condition showing some message in the view and returning result of the checking. I noticed that if first condition is false it will only show error message for the first method (and I need all of them to be checked) and no breakpoint is triggered inside these methods. I thought it was some kind of LLVM optimization so I created code like this:
-(IBAction)send {
BOOL correct = [self isCorrect1];
correct = correct && [self isCorrect2];
...
if (correct) {
[self sendRequest];
}
}
And is still not working correctly. Do I have to create new BOOL variable to store result for the check or is there some other way?
Since the first condition is evaluated to false, it won't check for the rest of the conditions and will go to the else part straightaway.
Try this.
BOOL finalResult = [self isCorrect1];
finalResult = [self isCorrect2] && finalResult;
finalResult = [self isCorrect3] && finalResult;
finalResult = [self isCorrect4] && finalResult;
...
if (finalResult) {
}
This will go through all of the isCorrect tests and will let you know if it passed all of them in the end or not.
The behaviour you see is the expected behaviour of the &&, namely, it "short-circuits" the evaluation, if it can determine the result in advance, before having evaluated all conditions:
expression-yielding-false && something-else
The result of the above is completely determined by the first part; regardless of what the second operand yields, the final result is false. This allows you to write something like:
if (obj != null && obj->count == 3)
{
...
}
If the && did not have the short-circuit behaviour, you'd have to write
if (obj != null)
{
if (obj->count == 3)
{
...
}
}
The || has a similar behaviour. In case of
something-yielding-true || anything
the right-hand side cannot affect the result value, as the left-hand side already returned true.
One possible work-around would be:
int succeeses = 0;
succeesses += [self isCorrect1]? 1 : 0;
succeesses += [self isCorrect2]? 1 : 0;
succeesses += [self isCorrect3]? 1 : 0;
if (successes == 3)
{
// All tests did succeed
}
else
{
// At least one failed.
}
If you need to know, which tests passed, and which failed, you can try:
BOOL passed1 = [self isCorrect1];
BOOL passed2 = [self isCorrect2];
BOOL passed3 = [self isCorrect3];
if (passed1 && passed2 && passed3)
{
// All tests did succeed
}
else
{
// At least one failed.
}
A more dense version of the above would be
int passed = 0;
passed |= [self isCorrect1]? (1 << 0) : 0;
passed |= [self isCorrect2]? (1 << 1) : 0;
passed |= [self isCorrect3]? (1 << 2) : 0;
if (passed == 7)
{
// All tests did succeed
}
else
{
if (passed & (1 << 0))
{
// First test passed
}
else
{
// First test failed
}
if (passed & (1 << 1))
{
// Second test passed
}
else
{
// Second test failed
}
if (passed & (1 << 2))
{
// Third test passed
}
else
{
// Third test failed
}
}
which is simply a more occult formulation of the version with a boolean variable per test tried.

Issue with DevExpress XtraTabControl

I am having a DevExpress XtraTabControl with 3 XtraTabPages.
I am trying to remove a Tabpage based on a condition and after removing for the last iteration,it is getting error.
My Code is
foreach (DevExpress.XtraTab.XtraTabPage ptp in tabContactsDetails.TabPages)
{
if (tabContactsDetails.TabPages.Contains(ptp))
{
if (ptp.Name == "tabPTP")
{
if (maxid == String.Empty || maxid == null || maxid == "lblHiddenDebtorID")
{
tabContactsDetails.TabPages.Remove(ptp);
}
else
{
}
}
}
}
and I am getting an error like
Collection was modified; enumeration operation may not execute.
You cannot change a collection while iterating through it!
What I do is the following:
List<XtraTabPage> tabPagesToBeRemoved = new List<XtraTabPage>();
foreach (XtraTabPage ptp in tabContactsDetails.TabPages)
{
if (shouldBeRemoved())
{
tabPagesToBeRemoved.Add(ptp);
}
}
foreach (XtraTabPage pageToBeRemoved in tabPagesToBeRemoved)
{
tabContactsDetails.TabPages.Remove(pageToBeRemoved);
}

Resources