Axapta Validation Override Always Executes Twice - validation

In most cases, validation methods I've overridden execute twice each time the parent field is changed. Everything still works, but the InfoLog displays double messages every time.
Is there any way to prevent this?
Thanks
public boolean validate()
{
boolean ret;
int exlowValue;
int lowValue;
int highValue;
int exhighValue;
str errorMessage;
;
ret = super();
//Make sure a numeric value was entered
if (ABC_RegExValidator::validateMe("integer", int2str (ABC_Checks_checkExtremeLow.value())))
{
//get the form values
exlowValue = ABC_Checks_checkExtremeLow.value();
lowValue = str2int(ABC_Checks_checkLow.valueStr());
highValue = str2int(ABC_Checks_checkHigh.valueStr());
exhighValue = str2int(ABC_Checks_checkExtremeHigh.valueStr());
//Extreme Low must be 0 or less than all others
if (exlowValue != 0)
{
//A non-zero value was entered; it must be less than all other fields
if ((exlowValue >= lowValue && lowValue > 0) || (exlowValue >= highValue && highValue > 0) || (exlowValue >= exhighValue && exhighValue > 0))
{
//Return an error
ret = checkfailed(strFmt("#ABC197", int2str(exlowValue)));
}
else
{
//Not greater than any other value
//Success!
ret = true;
} //Greater than all others?
}
else
{
//No errors
ret = true;
} // 0?
}
else
{
//Regular expression failed
//Return an error
ret = checkfailed("#ABC192");
} //Regular expression
return ret;
}

Your description of the problem is not really clear. One can override the valite method on a form control, the validate method on a form datasource and the validatefield method on the table. That's my knowledge of version 3.0.
And how do you mean the "parent field"? I presume the table field?
If I put info messages in each of these methods they only execute once when I modify a value. That's the case in 3.0. I don't know which version you're using.
Maybe you could be more precise about which validation method you're testing?

Related

AssertionError on ArrayList with same output

I know that this topic has been asked by many times and I search for all possible solutions but unfortunately nothing solves my problem.
Here's my test case:
#Test
public void whenFindAllBy_thenReturnListofViewPlanDetailDto() {
java.sql.Date startDate = new java.sql.Date(new Date().getTime());
java.sql.Date endDate = new java.sql.Date(new Date().getTime());
Plan planA = new Plan();
planA.setName("Plan A - 2018");
entityManager.persist(planA);
entityManager.flush();
Module moduleA = new Module();
moduleA.setName("CSS");
moduleA.setDescription("CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.");
entityManager.persist(moduleA);
Module moduleB = new Module();
moduleB.setName("HTML");
moduleB.setDescription("Hypertext Markup Language is the standard markup language for creating web pages and web applications.");
entityManager.persist(moduleB);
PlanDetail planDetailA = new PlanDetail();
planDetailA.setInstructor("Mozilla Firefox Foundation");
planDetailA.setStartDate(startDate);
planDetailA.setEndDate(endDate);
planDetailA.setModule(moduleA);
planDetailA.setPlan(planA);
entityManager.persist(planDetailA);
PlanDetail planDetailB = new PlanDetail();
planDetailB.setInstructor("W3 Schools");
planDetailB.setStartDate(startDate);
planDetailB.setEndDate(endDate);
planDetailB.setModule(moduleB);
planDetailB.setPlan(planA);
entityManager.persist(planDetailB);
entityManager.flush();
List<ViewPlanDetailDto> plandetails = new ArrayList<>();
plandetails.add(new ViewPlanDetailDto(planDetailA.getId(), planDetailA.getModule().getName(), planDetailA.getModule().getDescription(), planDetailA.getInstructor(), planDetailA.getStartDate(), planDetailA.getEndDate()));
plandetails.add(new ViewPlanDetailDto(planDetailB.getId(), planDetailB.getModule().getName(), planDetailB.getModule().getDescription(), planDetailB.getInstructor(), planDetailB.getStartDate(), planDetailB.getEndDate()));
assertEquals(planRepository.findAllBy(planA.getId()), plandetails);
}
Stacktrace:
java.lang.AssertionError: expected: java.util.ArrayList<[ViewPlanDetailDto(detailId=1, name=CSS, description=CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript., instructor=Mozilla Firefox Foundation, startDate=2018-07-06, endDate=2018-07-06), ViewPlanDetailDto(detailId=2, name=HTML, description=Hypertext Markup Language is the standard markup language for creating web pages and web applications., instructor=W3 Schools, startDate=2018-07-06, endDate=2018-07-06)]> but was: java.util.ArrayList<[ViewPlanDetailDto(detailId=1, name=CSS, description=CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript., instructor=Mozilla Firefox Foundation, startDate=2018-07-06, endDate=2018-07-06), ViewPlanDetailDto(detailId=2, name=HTML, description=Hypertext Markup Language is the standard markup language for creating web pages and web applications., instructor=W3 Schools, startDate=2018-07-06, endDate=2018-07-06)]>
What I try:
Override equals on PlanDetail, ViewPlanDetailDto, Plan
but it all failed.
Equals and Hashcode overrides:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof ViewPlanDetailDto))
return false;
ViewPlanDetailDto other = (ViewPlanDetailDto) obj;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (detailId == null) {
if (other.detailId != null)
return false;
} else if (!detailId.equals(other.detailId))
return false;
if (endDate == null) {
if (other.endDate != null)
return false;
} else if (!endDate.equals(other.endDate))
return false;
if (instructor == null) {
if (other.instructor != null)
return false;
} else if (!instructor.equals(other.instructor))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (startDate == null) {
if (other.startDate != null)
return false;
} else if (!startDate.equals(other.startDate))
return false;
return true;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((detailId == null) ? 0 : detailId.hashCode());
result = prime * result + ((endDate == null) ? 0 : endDate.hashCode());
result = prime * result + ((instructor == null) ? 0 : instructor.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((startDate == null) ? 0 : startDate.hashCode());
return result;
}
When I try to assert it it always fails even though the output is identical.
Based on IntelliJ's comparison failure, it highlighted on the trailing space on the expected part which I don't get how it ended having a trailing space.
You probably override equals() incorrectly .
To understand and correct your issue, you should start by the base : unit testing your equals() method (and by the way think of overriding hashCode() to be consistent with the equals() contract).
Whatever, overriding equals() by specifying all instance fields of the class to do some assertions in an unit test is generally something that you can avoid and that you have to if it gives an undesirable behavior to equals().
equals() has a semantic defined in Object.equals() :
Indicates whether some other object is "equal to" this one.
You should stick to that.
Generally I use a unit testing matcher library such as Harmcrest or AssertJ to perform assertions on the object's field in a non intrusive while being simple and clear.
With AssertJ, your assertion could look like :
Assertions.assertThat(planRepository.findAllBy(planA.getId()))
// assert result size
.hasSize(2)
// extract a field to assert
.extracting(ViewPlanDetailDto::getPlanDetail)
// extract still finer fields to assert
.extracting(PlanDetail::getId, p -> p.getModule().getName(), p -> p.getModule().geDescription(), ... other fields to assert)
// declare values expected
.containsExactly(Tuple.tuple(planDetailA.getId(), "CSS", "CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.",
planDetailB.getId(), "HTML", "Hypertext Markup Language is the standard markup language for creating web pages and web applications.",
... other expected tuples ));

Returning null if multiple instances are found

I have an IEnumerable and a predicate (Func) and I am writing a method that shall return a value if only one instance in the list matches the predicate. If the criteria is matched by none, then none was found. If the criteria is matched by many instances, then the predicate was insufficient to successfully identify the desired record. Both cases should return null.
What is the recommended way to express this in LINQ that does not result in multiple enumerations of the list?
The LINQ operator SingleOrDefault will throw an exception if multiple instances are found.
The LINQ operator FirstOrDefault will return the first even when multiple was found.
MyList.Where(predicate).Skip(1).Any()
...will check for ambiguity, but will not retain the desired record.
It seems that my best move is to grab the Enumerator from MyList.Where(predicate) and retain the first instance if accessing the next item fails, but it seems slightly verbose.
Am I missing something obvious?
The "slightly verbose" option seems reasonable to me, and can easily be isolated into a single extension method:
// TODO: Come up with a better name :)
public static T SingleOrDefaultOnMultiple<T>(this IEnumerable<T> source)
{
// TODO: Validate source is non-null
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
return default(T);
}
T first = iterator.Current;
return iterator.MoveNext() ? default(T) : first;
}
}
Update: Here is a more general approach which might be more reusable.
public static IEnumerable<TSource> TakeIfCountBetween<TSource>(this IEnumerable<TSource> source, int minCount, int maxCount, int? maxTake = null)
{
if (source == null)
throw new ArgumentNullException("source");
if (minCount <= 0 || minCount > maxCount)
throw new ArgumentException("minCount must be greater 0 and less than or equal maxCount", "minCount");
if (maxCount <= 0)
throw new ArgumentException("maxCount must be greater 0", "maxCount");
int take = maxTake ?? maxCount;
if (take > maxCount)
throw new ArgumentException("maxTake must be lower or equal maxCount", "maxTake");
if (take < minCount)
throw new ArgumentException("maxTake must be greater or equal minCount", "maxTake");
int count = 0;
ICollection objCol;
ICollection<TSource> genCol = source as ICollection<TSource>;
if (genCol != null)
{
count = genCol.Count;
}
else if ((objCol = source as ICollection) != null)
{
count = objCol.Count;
}
else
{
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext() && ++count < maxCount);
}
}
bool valid = count >= minCount && count <= maxCount;
if (valid)
return source.Take(take);
else
return Enumerable.Empty<TSource>();
}
Usage:
var list = new List<string> { "A", "B", "C", "E", "E", "F" };
IEnumerable<string> result = list
.Where(s => s == "A")
.TakeIfCountBetween(1, 1);
Console.Write(string.Join(",", result)); // or result.First()

Algorith that determinates frequency of string combinations MQL4

I have csv file like this:
1392249600;EUR;CHF;USD;JPY;GBP
1392163200;GBP;JPY;USD;CHF;EUR
1392076800;GBP;CHF;EUR;JPY;USD
1391990400;JPY;USD;EUR;CHF;GBP
1391904000;GBP;EUR;CHF;USD;JPY
1391731200;GBP;EUR;CHF;JPY;USD
1391644800;EUR;CHF;USD;JPY;GBP
1391558400;JPY;USD;EUR;CHF;GBP
There can be over 15 000 rows in that file. I am trying to write code that could do such thing:
1.Takes first row saves it as parent. Then takes next 3 days as that childs.
2.Counts how often and which combination off childs with that parent are inside this file.
3.It creates something like summary for that so I could read todays combination and script shows the only the most frequent child combinations for next 3 days.
I don't have mathematical thinking so I have big problems to find solution myself.
What I think first I need script that generates all posible combinations of these colums made of EUR,CHF,USD,JPY,GBP so there is posible 5*4*3*2*1 = 120 combinations. Because they cant repeat in single row.
It will be like this.
First parent will be combination from first row like this: EUR;CHF;USD;JPY;GBP
Then 3 childs would be
GBP;JPY;USD;CHF;EUR
GBP;CHF;EUR;JPY;USD
JPY;USD;EUR;CHF;GBP
It saves this combination off parent and child elements.
Then again it starts from begining of the file, but moves one row below(like iteration +1).
then next all childs would be
GBP;CHF;EUR;JPY;USD
JPY;USD;EUR;CHF;GBP
GBP;EUR;CHF;USD;JPY
And again it saves these combinations for counting and make some frequency results.
And this cycle repeats for all rows on csv file.
Is there maybe some tips I should consider how to create this type of programm ?
Any tip would be great !
Thank You Very Much!
BB
Can you please clarify whether first value in a row in your file is date/time? 1392249600;EUR;CHF;USD;JPY;GBP
If yes, are you expecting that there will total 4 rows with the same date/time?
Or else you just need to go sequentially and use Line-1 as parent and then Line-2, Line-3, Line-4 as child and goes on... so that Line-5 becomes parent again?
To check whether country code is equivalent or not, you can use below kind of code. I am not 100% sure about your requirement, please correct me if you think this is not what you are looking for and I will try to answer you in other way:
package com.collections;
public class CountryCodeComparison {
public static void main(String[] args) {
//Read every row and sequentially insert value in CountryCode object.
//For ex. your row is: 1392163200;GBP;JPY;USD;CHF;EUR
String s1 = "1392163200;GBP;JPY;USD;CHF;EUR";
String [] array1 = s1.split(";");
CountryCode cc1 = new CountryCode(array1[1], array1[2], array1[1], array1[4], array1[5]);
//For ex. your row is: 1392076800;GBP;CHF;EUR;JPY;USD
String s2 = "1392076800;GBP;CHF;EUR;JPY;USD";
String [] array2 = s2.split(";");
CountryCode cc2 = new CountryCode(array2[1], array2[2], array2[1], array2[4], array2[5]);
if(cc1.equals(cc2)) {
System.out.println("Both CountryCode objects are equal.");
} else {
System.out.println("Both CountryCode objects are NOT equal.");
}
}
}
class CountryCode {
private String countryCode1;
private String countryCode2;
private String countryCode3;
private String countryCode4;
private String countryCode5;
public CountryCode(String countryCode1, String countryCode2,
String countryCode3, String countryCode4, String countryCode5) {
this.countryCode1 = countryCode1;
this.countryCode2 = countryCode2;
this.countryCode3 = countryCode3;
this.countryCode4 = countryCode4;
this.countryCode5 = countryCode5;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((countryCode1 == null) ? 0 : countryCode1.hashCode());
result = prime * result
+ ((countryCode2 == null) ? 0 : countryCode2.hashCode());
result = prime * result
+ ((countryCode3 == null) ? 0 : countryCode3.hashCode());
result = prime * result
+ ((countryCode4 == null) ? 0 : countryCode4.hashCode());
result = prime * result
+ ((countryCode5 == null) ? 0 : countryCode5.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CountryCode other = (CountryCode) obj;
if (countryCode1 == null) {
if (other.countryCode1 != null)
return false;
} else if (!countryCode1.equals(other.countryCode1))
return false;
if (countryCode2 == null) {
if (other.countryCode2 != null)
return false;
} else if (!countryCode2.equals(other.countryCode2))
return false;
if (countryCode3 == null) {
if (other.countryCode3 != null)
return false;
} else if (!countryCode3.equals(other.countryCode3))
return false;
if (countryCode4 == null) {
if (other.countryCode4 != null)
return false;
} else if (!countryCode4.equals(other.countryCode4))
return false;
if (countryCode5 == null) {
if (other.countryCode5 != null)
return false;
} else if (!countryCode5.equals(other.countryCode5))
return false;
return true;
}
}

X++ Coming Out Of QueryRun In Fetch Method

I can't seem to find the resolution for this. I have modified the Fetch method in a report, so that if the queryRun is changed, and the new ID is fetched, then the while loop starts over and a new page appears and 2 elements are executed. This part works fine, the next part does not, in each ID there are several Records which I am using Element.Execute(); and element.Send(); to process. What happens is, the first ID is selected, the element (body) of the reports is executed and the element is sent as expected, however the while loop does not go onto the next ID?
Here is the code;
public boolean fetch()
{
APMPriorityId oldVanId, newVanId;
LogisticsControlTable lLogisticsControlTable;
int64 cnt, counter;
;
queryRun = new QueryRun(this);
if (!queryRun.prompt() || !element.prompt())
{
return false;
}
while (queryRun.next())
{
if (queryRun.changed(tableNum(LogisticsControlTable)))
{
lLogisticsControlTable = queryRun.get(tableNum(LogisticsControlTable));
if (lLogisticsControlTable)
{
info(lLogisticsControlTable.APMPriorityId);
cnt = 0;
oldVanId = newVanId;
newVanId = lLogisticsControlTable.APMPriorityId;
if(newVanId)
{
element.newPage();
element.execute(1);
element.execute(2);
}
}
if (lLogisticsControlTable.APMPriorityId)
select count(recId) from lLogisticsControlTable where lLogisticsControlTable.APMPriorityId == newVanId;
counter = lLogisticsControlTable.RecId;
while select lLogisticsControlTable where lLogisticsControlTable.APMPriorityId == newVanId
{
cnt++;
if(lLogisticsControlTable.APMPriorityId == newVanId && cnt <= counter)
{
element.execute(3);
element.send(lLogisticsControlTable);
}
}
}
}
return true;
}
You are using lLogisticsControlTable as a target of both a queryRun.get() and a while select. However these two uses interfere; there are two SQL cursors to control.
Use two different record variables.

How to get out of repetitive if statements?

While looking though some code of the project I'm working on, I've come across a pretty hefty method which does
the following:
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
if (data != null)
{
if (data.A == null)
{
data.A = fieldName;
_dataRepository.InsertOrUpdate(data);
return "A";
}
if (data.B == null)
{
data.B = fieldName;
_dataRepository.InsertOrUpdate(data);
return "B";
}
// keep going data.C through data.Z doing the exact same code
}
}
Obviously having 26 if statements just to determine if a property is null and then to update that property and do a database call is
probably very naive in implementation. What would be a better way of doing this unit of work?
Thankfully C# is able to inspect and assign class members dynamically, so one option would be to create a map list and iterate over that.
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
List<string> props = new List<string>();
props.Add("A");
props.Add("B");
props.Add("C");
if (data != null)
{
Type t = typeof(data).GetType();
foreach (String entry in props) {
PropertyInfo pi = t.GetProperty(entry);
if (pi.GetValue(data) == null) {
pi.SetValue(data, fieldName);
_dataRepository.InsertOrUpdate(data);
return entry;
}
}
}
}
You could just loop through all the character from 'A' to 'Z'. It gets difficult because you want to access an attribute of your 'data' object with the corresponding name, but that should (as far as I know) be possible through the C# reflection functionality.
While you get rid of the consecutive if-statements this still won't make your code nice :P
there is a fancy linq solution for your problem using reflection:
but as it was said before: your datastructure is not very well thought through
public String DataField(int id, string fieldName)
{
var data = new { Z = "test", B="asd"};
Type p = data.GetType();
var value = (from System.Reflection.PropertyInfo fi
in p.GetProperties().OrderBy((fi) => fi.Name)
where fi.Name.Length == 1 && fi.GetValue(data, null) != null
select fi.Name).FirstOrDefault();
return value;
}
ta taaaaaaaaa
like that you get the property but the update is not yet done.
var data = _dataRepository.Find(id);
If possible, you should use another DataType without those 26 properties. That new DataType should have 1 property and the Find method should return an instance of that new DataType; then, you could get rid of the 26 if in a more natural way.
To return "A", "B" ... "Z", you could use this:
return (char)65; //In this example this si an "A"
And work with some transformation from data.Value to a number between 65 and 90 (A to Z).
Since you always set the lowest alphabet field first and return, you can use an additional field in your class that tracks the first available field. For example, this can be an integer lowest_alphabet_unset and you'd update it whenever you set data.{X}:
Init:
lowest_alphabet_unset = 0;
In DataField:
lowest_alphabet_unset ++;
switch (lowest_alphabet_unset) {
case 1:
/* A is free */
/* do something */
return 'A';
[...]
case 7:
/* A through F taken */
data.G = fieldName;
_dataRepository.InsertOrUpdate(data);
return 'G';
[...]
}
N.B. -- do not use, if data is object rather that structure.
what comes to my mind is that, if A-Z are all same type, then you could theoretically access memory directly to check for non null values.
start = &data;
for (i = 0; i < 26; i++){
if ((typeof_elem) *(start + sizeof(elem)*i) != null){
*(start + sizeof(elem)*i) = fieldName;
return (char) (65 + i);
}
}
not tested but to give an idea ;)

Resources