I'm creating an decision table using Drools and having trouble with the greater than character ('>').
I saw on the drools documentation that you could use '>' and '<' but I seem to get something wrong.
The column is (I don't have enough reputation yet to post images):
|CONDITION|
| | (empty cell)
|duration >|
|Duration|
|50|
|200|
The thing is that the architecture doesn't allow me to get the full object. I can only have some fields from the RemoteObject.
So the thing I can do is:
Integer duration = getRemoteObjectDuration();
kSession.insert(duration);
kSession.fireAllRules();
Which results in:
[6,2]: [ERR 102] Line 6:2 mismatched input '>' in rule "RuleTable_11"
[14,2]: [ERR 102] Line 14:2 mismatched input '>' in rule "RuleTable_12"
[0,0]: Parser returned a null Package
I could create a dummy object containing my field, but there must be something better to do.
Does anyone have an idea about this?
To match an Integer you can use a rule like
rule findInt
when
Integer( $iv: intValue > 42 )
then
System.out.println( "got an Integer > 42: " + $iv );
end
and, consequently, a spreadsheet column according to
CONDITION
Integer
intValue >
- ... -
42
This is, of course, doomed to fail when you have several Integer objects floating around in working memory, not being able to identify what is what.
For your predicament I'd create a shadow object for holding all fields of the remote object rather than wrap the fields individually.
Thanks to laune's comment, I finally made it work, but I had to create a custom object only containing the field I needed and I wrote the name of this new class below CONDITION.
So consider a class A with two String variables "name" and "value"
class B contains a variable which is Set of A
Set<A> allVariables
is a set that would look like this
A.name="$var1"
A.value = "x+10>2"
A.name="$var2"
A.value="11+y%10==0"
A.name="$var3"
A.value="$var1 && $var2"
What I need to do is evaluate these expressions. I'm using jexl for this. I need to iterate through the Set and replace these variable names with their respective values.
In this case, the object with name $var3 needs to be replaced with "x+10>2 && 11+y%10==0"
How do I do this?
You create 2 Hashmap, translated and toTranslate.
You parse your Set.
For each A in your Set, you look at value. If value contains any number of $element (started by $ sign), you look for this $element in your translated Hashmap keys.
If it's in there, you replace the occurrences of $element by the value found in your translated hashmap.
You do this for each different $element you found in your A object.
If all $element have been translated, you add your object A into the translated hashmap (key = name, value = value).
Else, you add it to your toTranslate hashmap.
Once all your Set has been parsed, you've got 2 hashmaps.
You create a while loop: while toTranslate hashmap is not empty, you take each value, and try to translate the $element within it by the ones in your translate hashmap.
Be careful, you may end with an infinite loop. One good thing to do would be to make sure that each time you loop on the toTranslate hashmap, the numbers of its elements is reduced. If not you're in an infinite loop.
I don't think it needs to be recursive. I think just this would work:
bool madeReplacement;
do:
bool madeReplacement = false
For each member of the set, X:
For each other member of the set, Y:
Replace all instances of Y.name with Y.value in X.value. If you replaced anything, madeReplacement = true.
while (madeReplacement)
Example:
$var1 is value 1
$var2 is value $var1
$var3 is value $var2 + 2
$var3.value contains $var2, replace $var2 with $var1 -> $var1 + 2
$var2.value contains $var1, replace $var1 with 1 -> 1
$var3.value contains $var1, replace $var1 with 1 -> 1 + 2
No value contains any other name, execution finished.
Even though we 'evaluated out of order' we eventually got the right answer anyway. However, this algorithm can be O(n^3) in the worst case (imagine if you had n variables that referenced each other in a long chain, and you started the replacement on the wrong end). One way to solve this would be to, when you X.value contains Y.name, first evaluate Y.value recursively (by doing the same loop-over-the-rest-of-the-set). This makes it O(n^2) worst case, so your suspicion that a recursive approach is appropriate may be correct ;)
(I wasn't sure if variable names were guaranteed to start with $, so I wrote it so it would not matter)
System.out.println("neon.mems.cmu.edu/people/".split("/").length); // output is 2
I was doing some url processing. To my surprise I just got the result above. I thought the number of elements could be the number of splitters plus one.
I didn't realize the last empty string(or just null) is cut off from the splitted array until now. I wonder if this is the case with every programming language.
No that's not the case for every programming language and there is no universal specification so there is no reason it should be.
Go
a := strings.Split("neon.mems.cmu.edu/people/", "/")
fmt.Println(len(a)) // prints 3
Javascript
Type this in the console of your browser :
"neon.mems.cmu.edu/people/".split('/')
The result is
["neon.mems.cmu.edu", "people", ""]
What you should do when a match is empty isn't something obvious or inherent to the split concept. A proof of that is that old Internet Explorer versions did remove those empty matches.
why it is discarded empty string?
String#split(regx) internally call String#split(regx,0) which execute Pattern.compile(regex).split(this, limit); actually - code snippet
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
resultSize--;
where empty string has been discarded from resultSize if limit is 0.
How to get desired result?
String#split(regx,limit) use get desired result.
System.out.println("neon.mems.cmu.edu/people/".split("/",3).length);
Result :
3
And about language specification I am agree with #dystroy
Is there any built in support for array in XQuery? For example, if we want to implement
the simple java program in xquery how we would do it:
(I am not asking to translate the entire program into xquery, but just asking
how to implement the array in line number 2 of the below code to xquery? I am
using marklogic / xdmp functions also).
java.lang.String test = new String("Hello XQuery");
char[] characters = test.toCharArray();
for(int i = 0; i<characters.length; i++) {
if(character[i] == (char)13) {
character[i] = (char) 0x00;
}
}
Legend:
hex 0x00 dec 0 : null
hex 0x0d dec 13: carriage return
hex 0x0a dec 10: line feed
hex 0x20 dec 22: dquote
The problem with converting your sample code to XQuery is not the absence of support for arrays, but the fact that x00 is not a valid character in XML. If it weren't for this problem, you could express your query with the simple function call:
translate($input, '', '')
Now, you could argue that's cheating, it just happens so that there's a function that does exactly what you are trying to do by hand. But if this function didn't exist, you could program it in XQuery: there are sufficient primitives available for strings to allow you to manipulate them any way you want. If you need to (and it's rarely necessary) you can convert a string to a sequence of integers using the function string-to-codepoints(), and then take advantage of all the XQuery facilities for manipulating sequences.
The lesson is, when you use a declarative language like XQuery or XSLT, don't try to use the same low-level programming techniques you were forced to use in more primitive languages. There's usually a much more direct way of expressing the problem.
XQuery has built-in support for sequences. The function tokenize() (as suggested by #harish.ray) returns a sequence. You can also construct one yourself using braces and commas:
let $mysequence = (1, 2, 3, 4)
Sequences are ordered lists, so you can rely on that. That is slightly different from a node-set returned from an XPath, those usually are document-ordered.
On a side mark: actually, everything in XQuery is either a node-set or a sequence. Even if a function is declared to return one string or int, you can treat that returned value as if it is a sequence of one item. No explicit casting is necessary, for which there are no constructs in XQuery anyhow. Functions like fn:exists() and fn:empty() always work.
HTH!
Just for fun, here's how I would do this in XQuery if fn:translate did not exist. I think Michael Kay's suggestion would end up looking similar.
let $test := "Hello XQuery"
return codepoints-to-string(
for $c in string-to-codepoints($test)
return if ($c eq 32) then 44 else $c)
Note that I changed the transformation because of the problem he pointed: 0 is not a legal codepoint. So instead I translated spaces to commas.
With MarkLogic, another option is to use http://docs.marklogic.com/json:array and its associated functions. The json:set-item-at function would allow coding in a vaguely imperative style. Coding both variations might be a good learning exercise.
There are two ways to do this.
Firstly you can create an XmlResults object using
XmlManager.createResults(), and use XmlResults.add() to add your
strings to this. You can then use the XmlResults object to set the
value of a variable in XmlQueryContext, which can be used in your
query.
Example:
XmlResults values = XMLManager.createResults();
values.add(new XmlValue("value1"));
values.add(new XmlValue("value2"));
XmlQueryContext.setVariableValue("files", values);
The alternative is to split the string in XQuery. You
can do this using the tokenize() function, which works using a
regular expression to match the string separator.
http://www.w3.org/TR/xpath-functions/#func-tokenize
Thanks.
A little outlook: XQuery 3.1 will provide native support for arrays. See http://www.w3.org/TR/xquery-31/ for more details.
You can construct an array like this:
$myArray = tokenize('a b c d e f g', '\s')
// $myArray[3] -> c
Please note that the first index of this pseudo-array is 1 not 0!
Since the question "How to use or implement arrays in XQuery?" is being held generic (and thus shows up in search results on this topic), I would like to add a generic answer for future reference (making it a Community Wiki, so others may expand):
As Christian Grün has already hinted at, with XQuery 3.1 XQuery got a native array datatype, which is a subtype of the function datatype.
Since an array is a 'ordered list of values' and an XPath/XQuery sequence is as well, the first question, which may arise, is: "What's the difference?" The answer is simple: a sequence can not contain another sequence. All sequences are automatically flattened. Not so an array, which can be an array of arrays. Just like sequences, arrays in XQuery can also have any mix of any other datatype.
The native XQuery array datatype can be expressed in either of two ways: As [] or via array {}. The difference being, that, when using the former constructor, a comma is being considered a 'hard' comma, meaning that the following array consists of two members:
[ ("apples", "oranges"), "plums" ]
while the following will consist of three members:
array { ("apples", "oranges"), "plums" }
which means, that the array expression within curly braces is resolved to a flat sequence first, and then memberized into an array.
Since Array is a subtype of function, an array can be thought of as an anonymous function, that takes a single parameter, the numeric index. To get the third member of an array, named $foo, we thus can write:
$foo(3)
If an array contains another array as a member you can chain the function calls together, as in:
$foo(3)(5)
Along with the array datatype, special operators have been added, which make it easy to look up the values of an array. One such operator (also used by the new Map datatype) is the question mark followed by an integer (or an expression that evaluates to zero or more integers).
$foo?(3)
would, again, return the third member within the array, while
$foo?(3, 6)
would return the members 3 and 6.
The parenthesis can be left out, when working with literal integers. However, the parens are needed, to form the lookup index from a dynamic expression, like in:
$foo?(3 to 6)
here, the expression in the parens gets evaluated to a sequence of integers and thus the expression would return a sequence of all members from index position 3 to index position 6.
The asterisk * is used as wildcard operator. The expression
$foo?*
will return a sequence of all items in the array. Again, chaining is possible:
$foo?3?5
matches the previos example of $foo(3)(5).
More in-depth information can be found in the official spec: XML Path Language (XPath) 3.1 / 3.11.2 Arrays
Also, a new set of functions, specific to arrays, has been implemented. These functions resinde in the namespace http://www.w3.org/2005/xpath-functions/array, which, conventionally, is being prefixed with array and can be found referenced in here: XPath and XQuery Functions and Operators 3.1 / 17.3 Functions that Operate on Arrays
I'm currently working on a basic parser in Java and I have run into a problem when it comes to loops. Say I want to parse a while loop it would look something like:
a = 0
WHILE a < 10
a = a + 1
WEND
This example contains 4 expressions one of which will only need to be parsed ones the others will need to be parsed 10 times. The first one being the initial a = 0, second and third being on each side of the condition in the WHILE statement and the last one being within the WHILE block.
When I wrote the interpreted for this it loads the expression class into 4 different variables as new, the reevaluates them for each time it runs.
My problem is that even though they are initially loaded as new classes each time, there is over flow between them so when I re-parse them all of them looks like the last one:
a + 1
Any advice on how to circumvent this?
The code base is rather big so I wont post it here but its available at: http://git.life-hack.org/basic-parser/tree/src/parser
The file I'm working in is LoopBlock.java