Validation of Conditional String Android - java

I have been trying to validate a sample string which I read from a file. I want to check if the condition in the given string evaluates to true or false.
String Test = "( ((10>20) & (10>5)) & (7>9) ) | (123>45)";
How can I do that using Java. I have been trying to split the brackets and operators. Is there any easy way to solve this kind of textual expressions?
I have tried JSR.JAR but I'm getting
java.lang.NoClassDefFoundError: Failed resolution of: Lsun/misc/Service; at javax.script.ScriptEngineManager.initEngines(ScriptEngineManager.java:108)at javax.script.ScriptEngineManager.access$000(ScriptEngineManager.java:55)at javax.script.ScriptEngineManager$1.run(ScriptEngineManager.java:98)at java.security.AccessController.doPrivileged(AccessController.java:45)at javax.script.ScriptEngineManager.init(ScriptEngineManager.java:96)at javax.script.ScriptEngineManager.(ScriptEngineManager.java:69)

It seems that android does not provide the java scripting engine.
Possibly you could use a third party library instead:
AndroidJSCore
J2V8 (java wrapper built on top of googles V8 engine)

Related

Clojure - compiling project with Java classes that are potentially not available

I am wrapping a java library in Clojure. Depending on the java library version, some classes exist or not, so my library can fail to even compile if it can't find the java classes. My idea was to use Reflector to use the string name of classes.
Example of what I'm trying to do:
(java.time.LocalDateTime/parse "2020-01-01")
would become
(if right-version?
(clojure.lang.Reflector/invokeStaticMethod "java.time.LocalDate" "parse" (into-array ["2020-01-01"]))
This works but is slower by a factor of 20x. Is there a better way to achieve the same? Can I use a macro that will define the correct function at compile time, depending on the version of the underlying library?
Thanks,
I have been using a macro solution to this problem for 6+ years in the Tupelo Library. It allows you to write code like:
(defn base64-encoder []
(if-java-1-8-plus
(java.util.Base64/getEncoder)
(throw (RuntimeException. "Unimplemented prior to Java 1.8: "))))
The macro itself is quite simple:
(defmacro if-java-1-11-plus
"If JVM is Java 1.11 or higher, evaluates if-form into code. Otherwise, evaluates else-form."
[if-form else-form]
(if (is-java-11-plus?)
`(do ~if-form)
`(do ~else-form)))
(defmacro when-java-1-11-plus
"If JVM is Java 1.11 or higher, evaluates forms into code. Otherwise, elide forms."
[& forms]
(when (is-java-11-plus?)
`(do ~#forms)))
and the version testing functions look like
;-----------------------------------------------------------------------------
; Java version stuff
(s/defn version-str->semantic-vec :- [s/Int]
"Returns the java version as a semantic vector of integers, like `11.0.17` => [11 0 17]"
[s :- s/Str]
(let [v1 (str/trim s)
v2 (xsecond (re-matches #"([.0-9]+).*" v1)) ; remove any suffix like on `1.8.0-b097` or `1.8.0_234`
v3 (str/split v2 #"\.")
v4 (mapv #(Integer/parseInt %) v3)]
v4))
(s/defn java-version-str :- s/Str
[] (System/getProperty "java.version"))
(s/defn java-version-semantic :- [s/Int]
[] (version-str->semantic-vec (java-version-str)))
(s/defn java-version-min? :- s/Bool
"Returns true if Java version is at least as great as supplied string.
Sort is by lexicographic (alphabetic) order."
[tgt-version-str :- s/Str]
(let [tgt-version-vec (version-str->semantic-vec tgt-version-str)
actual-version-vec (java-version-semantic)
result (increasing-or-equal? tgt-version-vec actual-version-vec)]
result))
(when-not (java-version-min? "1.7")
(throw (ex-info "Must have at least Java 1.7" {:java-version (java-version-str)})))
(defn is-java-8-plus? [] (java-version-min? "1.8")) ; ***** NOTE: version string is still `1.8` *****
(defn is-java-11-plus? [] (java-version-min? "11"))
(defn is-java-17-plus? [] (java-version-min? "17"))
The advantage of using the macro version is that you can refer to a Java class normally via the symbol java.util.Base64. Without macros, this will crash the compiler for older versions of Java even if wrapped by an if or when, since the symbol will be unresolved before the if or when is evaluated.
Since Java doesn't have macros, the only workaround in that case is to use the string "java.util.Base64"
and then Class/forName, etc, which is awkward & ugly. Since Clojure has macros, we can take advantage of conditional code compilation to avoid needing the powerful (but awkward) Java Reflection API.
Instead of copying or re-writing these functions into your own code, just use put
[tupelo "22.05.04"]
into your project.clj and away you go!
P.S.
You do not need to throw an exception if you detect an older version of Java. This example simply elides the code if the Java version is too old:
(t/when-java-1-11-plus
(dotest
(throws-not? (Instant/parse "2019-02-14T02:03:04.334Z"))
(throws-not? (Instant/parse "2019-02-14T02:03:04Z"))
(throws-not? (Instant/parse "0019-02-14T02:03:04Z")) ; can handle really old dates w/o throwing
...)
I could not tell from your question if your code uses Reflector on every call to the parse method. If so, you could instead define the Method once to use later many times:
(def right-version? true) ; set as appropriate
(def ^java.lang.reflect.Method parse-method
(when right-version?
(.getMethod (Class/forName "java.time.LocalDateTime")
"parse"
(into-array [java.lang.CharSequence]))))
(defn parse-local-date-time [s]
(when parse-method
(.invoke parse-method nil (into-array [s]))))
(parse-local-date-time "2020-01-01T14:30:00")
;; => #object[java.time.LocalDateTime 0x268fc120 "2020-01-01T14:30"]

Internal Server Error due to long XQuery duration (MarkLogic)

I have am currently running through some queries using the Java API provided by MarkLogic. I have installed it through adding the required dependencies to my library. The connection is set up using
DatabaseClient client = DatabaseClientFactory.newClient("localhost", 8000, secContext, ConnectionType.DIRECT);
From here some XQueries are ran using the code shown below
ServerEvaluationCall evl = client.newServerEval().xquery(query);
EvalResultIterator evr = evl.eval();
while(evr.hasNext()){
//Do something with the results
}
However, certain queries takes a long time to process causing an internal error.So Other then reducing the query time required, I am wondering if there is there a way to overcome this? Such as increasing of connection time limit for instance.
====Update===
Query used
xquery version "1.0-ml";
let $query-opts := /comments[fn:matches(text,".*generation.*")]
return(
$query-opts, fn:count($query-opts), xdmp:elapsed-time()
)
I know the regular expression used can be easily replaced by word-query. But for this instance I would like to just used regular expression for searching.
Example Data
<comments>
<date_commented>1998-01-14T04:32:30</date_commented>
<text>iCloud sync settings are not supposed to change after an iOS update. In the case of iOS 10.3 this was due to a bug.</text>
<uri>/comment/000000001415898</uri>
</comments>
On the basis of your provided data I'd use xdmp:estimate and a cts query.
xdmp:estimate(cts:search(doc(), cts:and-query((
cts:directory-query('/comment/'),
cts:element-word-query(xs:QName("text"), "generation")
))))
This will search all documents in your /comments/ directory for an element text containing the word generation. As you already know, this will only use indexes and does not require loading/parsing documents.
This also will not find any false-positives because there is only one text element per document/fragment (if your shown data is correct).

Elasticsearch Java API from 2.x to 5.x issues

I've updated to elasticsearch java library version 5.2.0.
In 2.x,
I was using SearchRequestBuilder.addField() in order to add a field to the search request. Nevertheless, It seems to be replaced. I've written the available methods intellisense is showing me. Which of them do I need to pick?
addDocValueField
addFieldDataField
addScriptField
addStoredField
storedFields
fields
SearchRequestBuilder.setNoFields is also removed. Which would be the alternative?
Currently, I'm calling scripts from Java using this code. Is there any more elegant way to call it in 5.x Java API?
Code:
return AggregationBuilders
.terms(this.getName())
.field(this.getName())
.script(new Script(
ScriptType.FILE,
"painless",
"year",
ImmutableMap.of("field", this.getName())
)
);
As you can see I setting field as script parameter. Nevertheless, I don't quite understand how to get it from script code.
Thanks.
When in doubt, go to the source
use setFetchSource(String[] includes, String[] excludes) instead
use setFetchSource(false) instead
if you need to execute this script for each document, you can use addScriptField()

Matching a single word inside optional parentheses

I am using java regex to match a specific platform.
For example, my list of strings are:
Ruby 2.1 (Puma)
Ruby 2.3 (Passenger Standalone)
Ruby 2.2 (Puma)
Ruby 2.2 (Passenger Standalone)
Ruby 1.9.6
From these I want to only pick the ones which are not Passenger standlone. ie. Ruby 2.1 (Puma) and Ruby 2.2 (Puma) and Ruby 1.9.6. The only restriction/condition is that the version name i.e Puma or Passenger Standalone is optional. And therefore the parenthesis and the string inside the parenthesis are optional
I am trying to use the following regex:
"Ruby (.*)\s+\(?\w{0,1}\)?$"
I have the options as an ArrayList of Strings. My method code looks like:
public void displayVersions(String platform) {
String regex = "Ruby (.*)\s+\(?\w{0,1}\)?$";
List<String> availableVersions = getAvailableVersions();
List<String> filtered = availableVersions.stream()
.filter(version -> version.matches(regex))
.collect(Collectors.toList());
System.out.println(filtered);
}
The regex is incorrect and I am not getting the correct results. I get the Passenger Standalone versions only. What am I doing wrong?
Fixed regex: Ruby ([0-9.]+)\s?\(?[^\s]*\)?$
You may also need to add /m option if the string to match is multiline
I personally suggest you https://regex101.com to check and debug regexes. For example https://regex101.com/r/c148v8/2
Ruby [0-9.]+ \((\S)\)
This will do the trick.
Ruby [0-9.]+ matches the ruby version
\((\S)\) matches any non-whitespace char within parenthesis.
Use nested optionals:
^Ruby \d+(\.\d+)*( \(?\w+\)?)?$
See live demo.

What does the #sign do?

I have seen the at (#) sign in Groovy files and I don't know if it's a Groovy or Java thing. I have tried to search on Google, Bing, and DuckDuckGo for the mystery at sign, but I haven't found anything. Can anyone please give me a resource to know more about what this operator does?
It's a Java annotation. Read more at that link.
As well as being a sign for an annotation, it's the Groovy Field operator
In Groovy, calling object.field calls the getField method (if one exists). If you actually want a direct reference to the field itself, you use #, ie:
class Test {
String name = 'tim'
String getName() {
"Name: $name"
}
}
def t = new Test()
println t.name // prints "Name: tim"
println t.#name // prints "tim"
'#' is an annotations in java/ Groovy look at the demo :Example with code
Java 5 and above supports the use of annotations to include metadata within programs. Groovy 1.1 and above also supports such annotations.
Annotations are used to provide information to tools and libraries.
They allow a declarative style of providing metadata information and allow it to be stored directly in the source code.
Such information would need to otherwise be provided using non-declarative means or using external files.
It can also be used to access attributes when parsing XML using Groovy's XmlSlurper:
def xml = '''<results><result index="1"/></results>'''
def results = new XmlSlurper().parseText(xml)
def index = results.result[0].#index.text() // prints "1"
http://groovy.codehaus.org/Reading+XML+using+Groovy's+XmlSlurper

Categories