I'm writing an app using iText 5G, I have seen a piece of code to doesn't allow that tables split at page end but that code was written in C#, I have converted almost of all the code to Java but I'm stuck in one line that I don't know the equivalent in Java.
The C# code:
public override IList<iTextSharp.text.IElement> End(iTextSharp.tool.xml.IWorkerContext ctx, iTextSharp.tool.xml.Tag tag, IList<iTextSharp.text.IElement> currentContent)
{
string keeprowstogetherattr = "keeprowstogether";
var retval = base.End(ctx, tag, currentContent);
if (tag.Attributes.ContainsKey(keeprowstogetherattr) && tag.Attributes[keeprowstogetherattr] == "true")
{
foreach (PdfPTable table in retval.OfType<PdfPTable>())
{
table.KeepRowsTogether(0);
}
}
return retval;
}
My Java code at the moment:
public List<Element> End(WorkerContext ctx, Tag tag, List<Element> currentContent)
{
{
String keeprowstogetherattr = "keeprowstogether";
List<Element> retval = super.end(ctx, tag, currentContent);
if (tag.getAttributes().containsKey(keeprowstogetherattr) && tag.getAttributes().get(keeprowstogetherattr) == "true");
{
for (PdfPTable table : retval.OfType<PdfPTable>())
{
table.keepRowsTogether(0);
}
}
return retval;
}
}
The line that I'm stuck:
PdfPTable table : retval.OfType<PdfPTable>()
I don't know the equivalent to C#'s OfType in Java.
Thanks.
EDIT: My min API is 19, so stream() doesn't work.
If you can't use the stream filters, the simplest way is probably to do an instanceof check inside the for loop:
for(Element e: retval) {
if(e instanceof PdfPTable) {
((PdfPTable) e).keepRowsTogether(0);
}
}
As stylistic notes, you should name your methods starting with lowercase letters (end), and that keeprowstogetherattr should be a constant field named KEEP_ROWS_TOGETHER_ATTR (or better yet, ATTR_KEEP_ROWS_TOGETHER) in both C# and Java.
Related
I'm trying to implement a CSRF token, but all the info is programmed with Java 8+ version, so what I need is some help rewriting this line in Java 6/7:
tokenCookie = Arrays.stream(httpReq.getCookies()).filter(c -> c.getName().equals(csrfCookieExpectedName)).findFirst().orElse(null);
Actually from that line I'm only getting the error in:
c -> c.getName().equals(csrfCookieExpectedName)
In addition to #GIO's answer, you could try for-each loop like this:
public Cookie getExpectedCookieName(Cookie[] cookies) {
for (Cookie c : cookies) {
if (c.getName().equals(csrfCookiesExpectedName)) {
return c;
}
}
return null;
}
and call it like this :
tokenCookie = getExpectedCookieName(httpReq.getCookies());
This is can be converted using a pretty simple for loop. What you need is basically to check every single element of the array, find the first matching element that you need an exit from the loop, if no element matches then simply return null;
public Cookie getExpectedCookieName() {
for (int i = 0; i < httpReq.getCookies().length; i++) {
if(httpReq.getCookies()[i].getName().equals(csrfCookiesExpectedName)) {
return httpReq.getCookies()[i];
}
}
return null;
}
I am busy with a project that extracts data from a xml file and displays it in a word document. I have created a method for this extraction, but I want to simplify it by using an array of methods.
This is just an example of how I test for certain information at the moment:
for (int i = 0; i < nodeMap.getLength(); i++) {
Node node = nodeMap.item(i);
if (node.getNodeName().equalsIgnoreCase("maximumRedeliveries")) {
if (node.getNodeValue().startsWith("{{")) {
retryLogic.setMaximumRedeliveries(extractPropertyName(node.getNodeValue(), propFileLocation));
} else {
retryLogic.setMaximumRedeliveries(node.getNodeValue());
}
}
if (node.getNodeName().equalsIgnoreCase("asyncDelayedRedelivery")) {
if (node.getNodeValue().startsWith("{{")) {
retryLogic.setAsyncDelayedRedelivery(extractPropertyName(node.getNodeValue(), propFileLocation));
} else {
retryLogic.setAsyncDelayedRedelivery(node.getNodeValue());
}
}
}
I am aiming to create an array for the if statement values, for example "maximumRedeliveries" and "asyncDelayedRedelivery" and an array for their corresponding methods, for example setMaximumRedeliveries(),setAsyncDelayedRedelivery(). I am unsure of how to create an array of methods, or if it's even possible?
This problem differs form Java - Creating an array of methods, because I use set methods and don't know how to implement it in that way.
First, ensure that extractPropertyName takes names with and without curly braces, and behaves like this:
String extractOptionalPropertyName(String name, String propFileLocation) {
return name..startsWith("{{") ? extractPropertyName(name, propFileLocation) : name;
}
This moves conditionals from your XML processing code into a helper:
String nodeName = node.getNodeName();
if (nodeName.equalsIgnoreCase("maximumRedeliveries")) {
retryLogic.setMaximumRedeliveries(extractOptionalPropertyName(node.getNodeValue(), propFileLocation));
} else if (nodeName.equalsIgnoreCase("asyncDelayedRedelivery")) {
retryLogic.setAsyncDelayedRedelivery(extractOptionalPropertyName(node.getNodeValue(), propFileLocation));
} ... // and so on
With these changes in place, you can follow the recipe from this other Q&A and make a Map<String,ValSetter> objects, like this:
interface ValSetter {
void set(RetryLogic logic, String val);
}
// The map can be made static in a class
Map<String,ValSetter> setterForName = new HashMap<>();
{ // Initializer block
setterForName.put("maximumredeliveries", new ValSetter() {public void set(RetryLogic logic, String val) { logic.setMaximumRedeliveries(val);}} );
setterForName.put("asyncrelayedredelivery", new ValSetter() {public void set(RetryLogic logic, String val) { logic.setAsyncDelayedRedelivery(val);}} );
}
Now your XML handler could look like this:
String nodeName = node.getNodeName();
ValSetter setter = setterForName.get(nodeName.toLowerCase());
if (setter != null) {
String val = extractOptionalPropertyName(node.getNodeValue(), propFileLocation);
setter.set(retryLogic, val);
} else {
// report an error
}
I have a set of incoming records, that needs to be evaluated under a set of logical clauses defined and stored. An example logical clause be like :
Acct1 != 'Y' AND Acct2 > 1004 AND Acct3 >= 96 AND Acct4 < 1004 AND Acct5 = 99 AND ((Acct6 <= 9090 OR Acct7 IN (A1,A2,A6) AND Acct1 NOT IN (A3,A4)) AND Formatted LIKE 'LINUX' AND Acct9 NOT LIKE 'WINDOWS' AND (Acct10 = 'N' AND NOT Acct11 = 'N') AND EditableField BETWEEN (10 AND 20) )
My data input to the clause be like :
map.put(Acct1,"Y")
map.put(Acct2,1010)
map.put(Acct3,99)
map.put(Acct4,1015)
map.put(Acct5,99)
map.put(Acct6,9090)
map.put(Acct7,"A3")
map.put(Formatted,"LINUX_INST")
map.put(Updated,"LINUX_TMP")
map.put(Acct10,"Y")
map.put(Acct11,"N")
map.put(EditableFIeld,25)
I have to evaluate the incoming records populated into the map onto the clause defined above and print true or false based on the evaluation result.
The clause conditions and map values will be changed and executed as well.
I have the following conditional clauses to be evaluated:
!=
>
>=
<
=
<=
IN(
NOT IN(
LIKE(
NOT LIKE(
BETWEEN(
AND
OR
AND NOT
OR NOT
I have tried using grammar generators but I am told that it is not a recommended solution for our application hence I am looking for java code and I have this detailed example for reference to AND,OR,=.
resolving logical operations - AND, OR, looping conditions dynamically and looking for snippets to build on top of that if possible.
If you want to avoid a parser generator, consider using a StreamTokenizer to implement a recursive descent parser, with one method for each grammar rule.
For a subset of your grammar, this should look roughly like this (and should be straightforward to extend to your full grammar):
public class Parser {
public static Node parse(String expr) {
StreamTokenizer tokenizer =
new StreamTokenizer(new StringReader(expr));
tokenizer.nextToken();
Parser parser = new Parser(tokenizer);
Node result = parser.parseExpression();
if (tokenizer.ttype != StreamTokenizer.TT_EOF) {
throw new RuntimeException("EOF expected, got "
+ tokenizer.ttype + "/" + tokenizer.sval);
}
private StreamTokenizer tokenizer;
private Parser(StreamTokenizer tokenizer) {
this.tokenizer = tokenizer;
}
private Node parseExpression() {
Node left = parseAnd();
if (tokenizer.ttype == StreamTokenizer.TT_WORD
&& tokenizer.sval.equals("OR")) {
tokenizer.nextToken();
return new OperationNode(OperationNode.Type.OR,
left, parseExpression());
}
return left;
}
private Node parseAnd() {
Node left = parseRelational();
if (tokenizer.ttype == StreamTokenizer.TT_WORD
&& tokenizer.sval.equals("AND")) {
tokenizer.nextToken();
return new OperationNode(OperationNode.Type.AND,
left, parseAnd());
}
return left;
}
private Node parseRelational() {
Node left = parsePrimary();
OperationNode.Type type;
switch (tokenizer.ttype) {
case '<': type = OperationNode.Type.LESS; break;
case '=': type = OperationNode.Type.EQUAL; break;
case '>': type = OperationNode.Type.GREATER; break;
default:
return left;
}
tokenizer.nextToken();
return new OperationNode(type, left, parseRelational());
}
private Node parsePrimary() {
Node result;
if (tokenizer.ttype == '(') {
tokenizer.nextToken();
result = parseExpression();
if (tokenizer.ttype != ')') {
throw new RuntimeException(") expected, got "
+ tokenizer.ttype + "/" + tokenizer.sval);
}
} else if (tokenizer.ttype == '"' || tokenizer.ttype == '\'') {
result = new LiteralNode(tokenizer.sval);
} else if (tokenizer.ttype == TT_NUMBER) {
result = new LiteralNode(tokenizer.nval);
} else if (tokenizer.ttype == StreamTokenizer.TT_WORD) {
result = new FieldNode(tokenizer.sval);
} else {
throw new RuntimeException("Unrecognized token: "
+ tokenizer.ttype + "/" + tokenizer.sval);
}
tokenizer.nextToken();
return result;
}
}
This assumes a Node object hierarchy like this:
interface Node {
Object eval(Map<String,Object> data);
}
class FieldNode implements Node {
private String name;
FieldNode(String name) {
this.name = name;
}
public Object eval(Map<String,Object> data) {
return data.get(name);
}
}
class LiteralNode implements Node {
private Object value;
FieldNode(Object value) {
this.value = value;
}
public Object eval(Map<String,Object> data) {
return value;
}
}
class OperationNode implements Node {
enum Type {
AND, OR, LESS, GREATER, EQUALS
}
private Type type;
private Node leftChild;
private Node rightChild;
OperationNode(Type type, Node leftChild, Node rightChild) {
this.type = type;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
public Object eval(Map<String,Object> data) {
Object left = leftChild.eval(data);
Object right = rightChild.eval(data);
switch (type) {
case AND: return ((Boolean) left) && ((Boolean) right);
case OR: return ((Boolean) left) || ((Boolean) right);
case LESS: return ((Comparable) left).compareTo(right) < 0;
case EQUALS: return left.equals(right);
case GREATE: return ((Comparable) left).compareTo(right) > 0;
default:
throw new RuntimeException("Invalid op: " + type);
}
}
To directly answer the question, a number of SO questions (e.g. 1, 2) describe the basics of writing a parser by hand, though in practice it is very unusual to write a parser manually outside of university compiler courses due to the boilerplate and exacting detail involved.
As discussed in the comments, it sounds like the main reason to avoid grammar generators is to avoid a dependency on outside libraries. However, when using a grammar generator (parser generator) like JavaCC (Java Compiler-Compiler), there are no JAR files or outside dependencies involved: The JavaCC binary converts a grammar specification into Java code, that can be run without involving any further libraries.
See this IBM tutorial, JoAnn Brereton's "Use JavaCC to build a user friendly boolean query language" (via archive.org) as an example, which incidentally involves a grammar for a search language not unlike yours.
Example inputs:
actor = "Christopher Reeve" and keyword=action and keyword=adventure
(actor = "Christopher Reeve" and keyword=action) or keyword=romance
actor = "Christopher Reeve" and (keyword=action or keyword=romance)
Grammar excerpts:
TOKEN :
{
<STRING : (["A"-"Z", "0"-"9"])+ >
<QUOTED_STRING: "\"" (~["\""])+ "\"" >
}
void queryTerm() :
{
}
{
(<TITLE> | <ACTOR> |
<DIRECTOR> | <KEYWORD>)
( <EQUALS> | <NOTEQUAL>)
( <STRING> | <QUOTED_STRING> )
|
<LPAREN> expression() <RPAREN>
}
Output files:
UQLParser.java
UQLParserConstants.java
UQLParserTokenManager.java
TokenMgrError.java
ParseException.java
Token.java
SimpleCharStream.java
This is one of several parser generators that you can consider; others, like yacc and bison, also generate standalone Java files without requiring outside libraries. If necessary, you can check the generated Java files directly into your repository, leaving the .jj compiler source file only if you need to adjust the syntax. (Though it would probably be better to compile freshly from source as part of your build process and avoid checking generated files into source control, this may better suit your constraints of a Java-only solution.)
This problem is sort of a continuation of How to write visitor classes for collections? - I tried that answer, but I find that the code works in eclipse, but has a null pointer problem in unix or windows. So now it looks like a different problem, so I created a new question.
I have uploaded the full code at https://sites.google.com/site/rogergdmn/ , Below is the summary.
Here are the details (the code is a variation of the LabeledExpr.g4 from the book) - I am trying to create an intermediate data structure by using the visitor classes. When I run in command line (in unix or windows), the line "why null e" is printed, but this line is not printed when I run in eclipse. How do I fix this bug?
This is the grammar:
prog: stat+ ;
stat: expr NEWLINE # printExpr
| NEWLINE # blank
;
expr: INT # int
;
These are the functions in EvalVisitor.java:
public Object visitInt(ExprParser.IntContext ctx) {
System.out.printf("visited----- 1\n");
int value = Integer.valueOf(ctx.INT().getText());
return new E(1, value);
}
public Object visitPrintExpr(ExprParser.PrintExprContext ctx) {
System.out.printf("visited----- 2\n");
E e = (E) visit(ctx.expr()); // evaluate the expr child
return new E(2, e);
}
public Object visitProg(ExprParser.ProgContext ctx) {
System.out.printf("visited----- 3\n");
List<ExprParser.StatContext> sL = ctx.stat();
List<E> eL = new ArrayList<E>();
for(ExprParser.StatContext s : sL) {
E e = (E) visit(s);
if(e==null) System.out.printf("why null e??\n");
eL.add(e);
}
return new E(7, eL);
}
This is the E class (only constructors present, to demonstrate the error):
public class E {
int typ;
int val;
E e1;
List<E> eL;
public E(int _typ, int _v) { typ = _typ; val = _v; }
public E(int _typ, E _e1) { typ = _typ; e1 = _e1; }
public E(int _typ, List<E> _eL) { typ = _typ; eL = _eL; }
}
The other codes are directly from the book example (http://pragprog.com/titles/tpantlr2/source_code , directory "starter").
BTW, a similar visitor code is shown at If/else statements in ANTLR using listeners and https://github.com/bkiers/Mu, and that code works fine for me. My code is pretty similar to that code, so I am not sure whats going wrong here.
You didn't override visitBlank, so any blank statement will return null from the visit method.
Edit: The difference between Eclipse and the other case is one of the following:
You could be using different input in the two cases. You'll need to examine the raw contents of the TokenStream to be sure.
You didn't include an explicit EOF at the end of your prog rule, so there is a possibility that your parser is ignoring some tokens of the input. To ensure all tokens are considered in all cases, add a reference to EOF at the end of the prog rule.
I am new to java and I want to create a very simple "word completion " program. I will be reading in a dictionary file and recursively adding the words into a Node array (size 26). I believe I have managed to do this successfully but I am not sure how to go through and print the matches. For the sake of testing, I am simply inserting 2 words at the moment by calling the function. Once everything is working, I will add the method to read the file in and remove junk from the word.
For example: If the words "test" and "tester" are inside the tree and the user enters "tes", it should display "test" and "tester".
If somebody could please tell me how to go through and print the matches (if any), I would really appreciate it. Full code is below.
Thank you
What you implemented is called "trie". You might want to look at the existing implementations.
What you used to store child nodes is called a hash table and you might want to use a standard implementations and avoid implementing it yourself unless you have very-very specific reasons to do that. Your implementation has some limitations (character range, for example).
I think, your code has a bug in method has:
...
else if (letter[val].flag==true || word.length()==1) {
return true;
}
If that method is intended to return true if there are strings starting with word then it shouldn't check flag. If it must return true if there is an exact match only, it shouldn't check word.length().
And, finally, addressing your question: not the optimal, but the simplest solution would be to make a method, which takes a string and returns a node matching that string and a method that composes all the words from a node. Something like this (not tested):
class Tree {
...
public List<String> matches(CharSequence prefix) {
List<String> result = new ArrayList<>();
if(r != null) {
Node n = r._match(prefix, 0);
if(n != null) {
StringBuilder p = new StringBuilder();
p.append(prefix);
n._addWords(p, result);
}
}
return result;
}
}
class Node {
...
protected Node _match(CharSequence prefix, int index) {
assert index <= prefix.length();
if(index == prefix.length()) {
return this;
}
int val = prefix.charAt(index) - 'a';
assert val >= 0 && val < letter.length;
if (letter[val] != null) {
return letter[val].match(prefix, index+1);
}
return null;
}
protected void _addWords(StringBuilder prefix, List<String> result) {
if(this.flag) {
result.add(prefix.toString());
}
for(int i = 0; i<letter.length; i++) {
if(letter[i] != null) {
prefix.append((char)(i + 'a'));
letter[i]._addWords(prefix, result);
prefix.delete(prefix.length() - 1, prefix.length());
}
}
}
}
Maybe a longshot here, but why don't you try regexes here? As far as i understand you want to match words to a list of words:
List<String> getMatches(List<String> list, String regex) {
Pattern p = Pattern.compile(regex);
ArrayList<String> matches = new ArrayList<String>();
for (String s:list) {
if (p.matcher(s).matches()) {
matches.add(s);
}
}
return matches
}