NatTable Filter using Regex - nattable

I am interested in using regular expressions in the NatTable filter. I have set up my code based on the following helpful links:
http://www.vogella.com/tutorials/NatTable/article.html#exercise-adding-a-filter-functionality-to-a-nattable
https://www.eclipse.org/forums/index.php/t/1069806/
From what I can gather, it basically boils down to adding the following code to your existing Filter:
FilterRowHeaderComposite<T> filterRowHeaderLayer = new
FilterRowHeaderComposite<>(filterStrategy,
sortHeaderLayer, columnHeaderDataLayer.
getDataProvider(), configRegistry);
int rowNum = 2;
configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR,
new FilterRowTextCellEditor(), DisplayMode.NORMAL,
FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + rowNum);
configRegistry.registerConfigAttribute(FilterRowConfigAttributes.
TEXT_MATCHING_MODE, TextMatchingMode.REGULAR_EXPRESSION,
DisplayMode.NORMAL,
FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + rowNum);
configRegistry.registerConfigAttribute(CellConfigAttributes.
DISPLAY_CONVERTER, new FilterRowRegularExpressionConverter(),
DisplayMode.NORMAL,
FilterRowDataLayer.FILTER_ROW_COLUMN_LABEL_PREFIX + rowNum);
The filtering seems to work in certain situations and not others. For example, assume I have a cell that has the data "This is a Test". If I use the expression *t, it will find the row (which is what I expect). If I use the expression *x, it will not find the row (which is what I expect). If I use the expression ^(123) it will not find the row (which is NOT what I expect). Am I doing something incorrect?
Thanks!

I think the issue is in the regular expression. It seems that the cardinality is missing. Using [^123]* it works as you expect it.
If you for example test the _6031_GlazedListsFilterExample and insert [^abc] for the Housenumber column, you will see all entries that have only a one digit value. Adding the * all rows appear.

Related

string match and remove each row in a postgresql

So in short:
I need to find all rows in the column Translation that begin with the letter M (M123 is one of the Prefixes) and then I need to remove the M123 and similar prefixes from all the rows.
For example, row 1 contains the following data:
M123 - This is translated from Spanish to English
And I need to remove the M123 - from the mentioned data. And this I need to do for the Translation column in every row in the table.
It's been a while since I actually did some SQL-Queries. So I tried a WHERE clause to find all the M prefixes but my query returns an empty search. Following is the query I am using atm:
SELECT Translation from Translation_Table where Translation like 'M';
I am a little bit confused right now. So any help is appreciated.
I sense that you might be wanting to do an update here, rather than a select:
UPDATE Translation_Table
SET Translation = REGEXP_REPLACE(Translation, 'M[0-9]+', '')
WHERE Translation ~ '^M[0-9]+';
addition to this answer following query will remove all occurence of M[any length of a number]
UPDATE Translation_Table
SET Translation = REGEXP_REPLACE(Translation, '[M[:digit:]]', '', 'g')
WHERE Translation ~ '.M[0-9]*';

Set new column definition by setColumnDefs doesn't work anymore

I'm trying to set new column definitions by calling setColumnDefs using the grid API. This doesn't work as expected. The names of the column headers will not be updated anymore!
See this Plunkr: Version 19.1.x
Version 19.0.0 is latest working version.
See this Plunkr: Version 19.0.0
For me it seems to be a bug!?
In my project I'm using Angular 5 and I notice the same behaviour.
I was able to reproduce your behaviour. The following (dirty) workaround works:
gridOptions.api.setColumnDefs([]);
gridOptions.api.setColumnDefs(newColDefs);
Setting the columnDefs to an empty array and then passing the newColDefs seems to achieve what you are looking for.
I suppose it up to the new way of change-detection on the latest version.
If you will update your code like that:
function updateColDef()
{
let data = [];
columnDefs.forEach(function(colDef) {
colDef.headerName = colDef.headerName + ' X ';
data.push(colDef);
})
data.push( {
headerName: 'New Column',
});
gridOptions.api.setColumnDefs(data);
}
It will work as expected.
Update:
When new columns are set, the grid will compare with current columns and work out which columns are old (to be removed), new (new columns created) or kept (columns that remain will keep their state including position, filter and sort).
Comparison of column definitions is done on 1) object reference comparison and 2) column ID eg colDef.colId. If either the object reference matches, or the column ID matches, then the grid treats the columns as the same column.
In the first case, it was an object comparison, on the second sample (after update) its colId case.
changes came from 19.1 version release
AG-1591 Allow Delta Changes to Column Definitions.

Parameter field with multiple values not working

Setup a Parameter field with multiple values to be used in a SQL query command and it does not work when more than one value is selected, but works fine with one value selected. And yes, the "Allow multiple values" flag is set to True under Options.
I am trying to go from this:
EMPBNFIT.BENEFITPLAN in ('CONSUMER CHOICE','HMO', 'HS HMO','HS NETWORK CHOICE','HS PPO BASIC NH RPN','HS PPO PLUS NH RPN','MFS CONSUMER CHOICE','NETWORK CHOICE','PPO BASIC NH RPN','PPO PLUS NH RPN','WAIVE MEDICAL')
to this:
WHERE EMPBNFIT.BENEFITPLAN in ('{?MyPlans}')
What a coincidence; had the same problem this morning. I was able to make a workaround in Crystal by converting the array of multiple parameters into a single string, then replacing the IN section with an INSTR comparison.
Make a formula called ParamFix with this logic:
REPLACE(JOIN({?MyPlans}, ","), "&", "; ")
In my case, the different values were separated by an &, but you can replace that based on what comes back from the tables. Then replace the IN comparison with:
INSTR({#ParamFix}, EMPBNFIT.BENEFITPLAN) > 0

UIMA Ruta: Copy the feature value from a contained annotation to a containing annotation

Note: This seems heavily related to Setting feature value to the count of containing annotation in UIMA Ruta. But I cannot quite apply the answer to my situation.
I am analyzing plain text documents where the following structure is assumed:
Document (one, of course)
Section (many)
Heading (one per section)
I am being asked to identify sections by checking whether their headings satisfy conditions. A useful and obvious sort of condition would be: does the heading match a given regular expression? A less-useful but perhaps more achievable condition would be: does the heading contain a given text?
I could and have already achieved this by taking a list of tuples of regular expressions and section titles, and at design time, for each member of the list, as such:
BLOCK(forEach) SECTION{} {
...
HEADING{REGEXP(".*table.*contents.*", true) ->
SETFEATURE("value", "Table of Contents")};
...
}
SECTION{ -> SETFEATURE("value", "Table of Contents")}
<- { HEADING.headingValue == "Table of Contents"; };
This approach is fairly straightforward but has a few big drawbacks:
It heavily violates the DRY principle
Even when writing the rule for just one section to identify, the rule author must copy the section title twice (it should only need to be specified once)
It makes the script needlessly long and unwieldy
It puts a big burden on the rule author, who in an ideal case, would only need to know Regex - not Ruta
So I wanted to refactor to achieve the following goals:
A text file is used to store the regular expressions and corresponding titles, and the rule iterates over these pairs
Features, rather than types, are used to differentiate different sections/headings (i.e. like above, using SECTION.value=="Table of Contents" and not TableOfContentsSection)
After looking over the UIMA Ruta reference to see which options were available to achieve these goals, I settled on the following:
Use a WORDTABLE to store tuples of section title, words to find / regex if possible, lookup type - so for instance, Table of Contents,contents,sectiontitles
Use MARKTABLE to mark an intermediate annotation type LookupMatch whose hint feature contains the section title and whose lookup feature contains the type of lookup we are talking about
For each HEADING, see if a LookupMatch.lookup == "sectiontitle" is inside, and if it is, copy the LookupMatch.hint to the heading's value field.
For each SECTION, see if a HEADING with a value is inside; if so, copy the value to the SECTION.value field.
It was not quite a surprise to find that implementing steps 3 and 4 was not so easy. That's where I am at and why I am asking for help.
// STEP 1
WORDTABLE Structure_Heading_WordTable =
'/uima/resource/structure/Structure_Heading_WordTable.csv';
// STEP 2
Document.docType == "Contract"{
-> MARKTABLE(LookupMatch, // annotation
2, // lookup column #
Structure_Heading_WordTable, // word table to lookup
true, // case-insensitivity
0, // length before case-insensitivity
"", // characters to ignore
0, // matches to ignore
"hint" = 1, "lookup" = 3 // features
)
};
// STEPS 3 AND 4 ... ???
BLOCK(ForEach) LookupMatch.lookup == "sectiontitle"{} {
???
}
HEADING{ -> SETFEATURE("value", ???)} <- {
???
};
Here is my first real stab at it:
HEADING{ -> SETFEATURE("value", lookupMatchHint)} <- {
LookupMatch.lookup == "HeadingWords"{ -> GETFEATURE("hint", lookupMatchHint)};
};
TL; DR
How can I conditionally copy a feature value from one annotation to another? GETFEATURE kind of assumes that you only get 1...

dataFrame keying using pandas groupby method

I new to pandas and trying to learn how to work with it. Im having a problem when trying to use an example I saw in one of wes videos and notebooks on my data. I have a csv file that looks like this:
filePath,vp,score
E:\Audio\7168965711_5601_4.wav,Cust_9709495726,-2
E:\Audio\7168965711_5601_4.wav,Cust_9708568031,-80
E:\Audio\7168965711_5601_4.wav,Cust_9702445777,-2
E:\Audio\7168965711_5601_4.wav,Cust_7023544759,-35
E:\Audio\7168965711_5601_4.wav,Cust_9702229339,-77
E:\Audio\7168965711_5601_4.wav,Cust_9513243289,25
E:\Audio\7168965711_5601_4.wav,Cust_2102513187,18
E:\Audio\7168965711_5601_4.wav,Cust_6625625104,-56
E:\Audio\7168965711_5601_4.wav,Cust_6073165338,-40
E:\Audio\7168965711_5601_4.wav,Cust_5105831247,-30
E:\Audio\7168965711_5601_4.wav,Cust_9513082770,-55
E:\Audio\7168965711_5601_4.wav,Cust_5753907026,-79
E:\Audio\7168965711_5601_4.wav,Cust_7403410322,11
E:\Audio\7168965711_5601_4.wav,Cust_4062144116,-70
I loading it to a data frame and the group it by "filePath" and "vp", the code is:
res = df.groupby(['filePath','vp']).size()
res.index
and the output is:
[E:\Audio\7168965711_5601_4.wav Cust_2102513187,
Cust_4062144116, Cust_5105831247,
Cust_5753907026, Cust_6073165338,
Cust_6625625104, Cust_7023544759,
Cust_7403410322, Cust_9513082770,
Cust_9513243289, Cust_9702229339,
Cust_9702445777, Cust_9708568031,
Cust_9709495726]
Now Im trying to approach the index like a dict, as i saw in examples, but when im doing
res['Cust_4062144116']
I get an error:
KeyError: 'Cust_4062144116'
I do succeed to get a result when im putting the filepath, but as i understand and saw in previouse examples i should be able to use the vp keys as well, isnt is so?
Sorry if its a trivial one, i just cant understand why it is working in one example but not in the other.
Rutger you are not correct. It is possible to "partial" index a multiIndex series. I simply did it the wrong way.
The index first level is the file name (e.g. E:\Audio\7168965711_5601_4.wav above) and the second level is vp. Meaning, for each file name i have multiple vps.
Now, this is correct:
res['E:\Audio\7168965711_5601_4.wav]
and will return:
Cust_2102513187 2
Cust_4062144116 8
....
but trying to index by the inner index (the Cust_ indexes) will fail.
You groupby two columns and therefore get a MultiIndex in return. This means you also have to slice using those to columns, not with a single index value.
Your .size() on the groupby object converts it into a Series. If you force it in a DataFrame you can use the .xs method to slice a single level:
res = pd.DataFrame(df.groupby(['filePath','vp']).size())
res.xs('Cust_4062144116', level=1)
That works. If you want to keep it as a series, boolean indexing can help, something like:
res[res.index.get_level_values(1) == 'Cust_4062144116']
The last option is a bit less readable, but sometimes also more flexibile, you could test for multiple values at once for example:
res[res.index.get_level_values(1).isin(['Cust_4062144116', 'Cust_6073165338'])]