guys! I need to create some sort of meta language which I could embed in XML and then parse with Java. For example:
<code>
[if value1>value2 then "Hello, Bob!" else "Hello, Jack"]
</code>
or
<code>
[if value1+2>value2 return true]
</code>
I need to implement conditional statements,arithmetics.
Any suggestions where should I start looking?
Java has a built-in JavaScript interpreter:
ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("JavaScript");
jsEngine.put("value1", 8);
jsEngine.put("value2", 9);
String script = "if(value1 + 2 > value2) {'Foo'} else {'Bar'}";
final Object result = jsEngine.eval(script);
System.out.println(result); //yields "Foo" String
Of course you are free to both load the script from anywhere you need and to provide it with any context (value and value2 in this example) you want.
See also Scripting for the Java Platform article.
A user here, Bart Kiers. Wrote a tutorial about creating a simple language in Java with ANTLR.
Java has a scripting API that you could use for this. Lookup the API documentation of the package javax.script.
You could include code in for example JavaScript in the code element, and execute that using the scripting API.
If you really want to develop your own language, start off with the interpreter pattern. If you just want to leverage somebody else's language in your Java code, look to integration ala JSP style embedded languages.
It is almost certain that a homemade language would suck, especially in the long run, so don't roll something on your own.
There are several jsp-like frameworks available, maybe one of those would do the trick:
JSTL/JSP EL (Expression Language) in a non JSP (standalone) context
Related
I have managed to perform the click operation with the following :
chromeDriver.findElement(By.xpath("//div[#class='button button-primary cookie-accept-all']")).click();
I did the investigation and found out that it is not recommended to use xpath and much better to refer to css.
How can i possible do the same i did above with #FindBy(className = )
In that case you can try something like this (not tested):
chromeDriver.findElement(By.cssSelector(".button .button-primary .cookie-accept-all']")).click();
But please check the documentation that is quite useful https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
Assume i have lots of variables
String not_id, not_section, not_steet, not_sqTotal, not_sqLiving, not_sqKitchen, not_flat, not_floor, not_floors, not_text, user_phone1, user_phone2, user_contact, not_region, not_district, not_settle, not_price, not_photo, not_date, not_date_till, not_up, not_premium, not_status;
not_id= not_section= not_steet= not_sqTotal= not_sqLiving=
not_sqKitchen= not_flat= not_floor= not_floors= not_text=
user_phone1= user_phone2= user_contact= not_region= not_district=
not_settle= not_price= not_photo= not_date= not_date_till= not_up=
not_premium= not_status=region_title=district_title=settle_title=section_title="";
i need to change their values using someFunction
not_id = someFunction(not_id);
How can i do such action for all variables?
Please, dont propose to use arrays, lists and other sort of collections if it assumes changing variable names to some uniform name.
I van to know if there is such possibility within java itself, eclipse ide or eclipse plugins.
This is going to lead to somewhat unmaintainable code, but you could do it pretty easily with a regular expression search & replace on that second statement, replacing "var_name=" with "var_name = someFunction(var_name);".
Find: ([^=])+=
Replace with: \1 = someFunction(\1);
is someFunction a java method? or it is some simple transformer that is changing from not_([a-z])(\w*) to not[A-Z]\2? If you are only changing variable names use eclipse's excellent refactoring rename bound to Ctrl+Shift+R that can change all occurrences taking to account scope rules
We have a function strip_tags in PHP which would strip all the tags and also you can exempt certain tags from being stripped out..
My question is whether there is anything similar in Java??
You could try using the JSoup library. That API provides a clean method:
For examples, have a look over here: Sanitize untrusted HTML:
String unsafe =
"<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Whitelist.basic());
// now: <p>Link</p>
The OWASP Anit-Samy project does that (and a lot more) https://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project
For simpler validation use the ESAPI Validator http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/org/owasp/esapi/Validator.html
Use can try JSoup. It's open source and available for download.
http://jsoup.org/apidocs/org/jsoup/Jsoup.html
Can you do the following with a Java ResourceBundle?
In the properties file...
example.dynamicresource=You currently have {0} accounts.
At runtime...
int accountAcount = 3;
bundle.get("example.dynamicresource",accountCount,param2,...);
To give a result of
"You currently have 3 accounts."
Not without using the MessageFormat class, such as:
String pattern = bundle.getString("example.dynamicresource");
String message = MessageFormat.format(pattern, accountCount);
On their own, ResourceBundle does not support property placeholders. The usual idea is to take the String you get from the bundle, and stick it into a MessageFormat, and then use that to get your parameterized message.
If you're using JSP/JSTL, then you can combine <fmt:message> and <fmt:param> to do this, which uses ResourceBundle and MessageFormat under the covers.
If you happen to be using Spring, then it has the ResourceBundleMessageSource which does something similar, and can be used anywhere in your program. This MessageSource abstraction (combined with MessageSourceAccessor) is much nicer to use than ResourceBundle.
There are various ways, depending on the view technology you're using. If you're using "plain vanilla" Java (e.g. Swing), then use MessageFormat API as answered before. If you're using a webapplication framework (which is true, if I judge your question history here correctly), then the way depends on the view technology and/or MVC framework you're using. If it is for example "plain vanilla" JSP, then you can use JSTL fmt:message for this.
<fmt:message key="example.dynamicresource">
<fmt:param value="${bean.accountCount}">
</fmt:message>
If it is for example JSF, you can use h:outputFormat for this.
<h:outputFormat value="#{bundle['example.dynamicresource']}">
<f:param value="#{bean.accountCount}">
</h:outputFormat>
Best place is to just consult the documentation of the technology/framework you're using (or to tell it here so that we can give better suited and more detailed answers).
Struts have a nice util called MessageResources which does exactly what you ask for....
e.g.
MessageResources resources = getResources(request, "my_resource_bundle"); // Call your bundle exactly like ResourceBundle.getBundle() method
resources.getMessage("example.dynamicresource",accountCount,param2,...);
Limitation
It only allows maximum of 3 parameters (i.e. resource attribute, param1, ..., param3).
I suggest using MessageFormat (if you want to use more than 3 parameter values) as suggested by David Sykes.
PS the getResources method is available only in the Struts Action class.
I don't think you can make this work for Non-English properties file.
My message.properties file has the following line:
info.fomat.log.message.start=Starting to parse log message in {0} format.
And my message_fr_FR.properties file has the following line:
info.fomat.log.message.start=A partir d'analyser le message connecter {0} format.
This code works only for the English one
String.format((String) messages .getString(GlobalConstants.MESSAGE_FORMAT_START), GlobalConstants.STR_JSON));
It does NOT replace the placeholder with the value when my language / locale is French :-(
Even MessageFormat.fomat() is no good
I don't believe ResourceBundle can do that itself, but String can:
String.format(bundle.getString("example.dynamicresource"), accountCount);
Remember that when using MessageFormat.format() you need to use a double quote ('') in your resource bundle if you want to express single quote (').
MessageFormoat#format will work for the case like:
greetingTo=Have Param, saying hello {0}
You can declare two methods like this where RB is a instance of ResourceBundle:
/**This is a method that takes the param to substitute the placeholder**/
public String getString(String key, Object... params ) {
try {
return MessageFormat.format(this.RB.getString(key), params);
} catch (MissingResourceException e) {
return "[" + key + "]";
}
}
/**Without a param, this will derectly delegate to ResourceBundle#getString**/
public String getString(String key) {
try {
return this.RB.getString(key);
} catch (MissingResourceException e) {
return "[" + key + "]";
}
}
I'll point out now, that I'm new to using saxon, and I've tried following the docs and examples in the package, but I'm just not having luck with this problem.
Basically, I'm trying to do some xml processing in java using saxon v8. In order to get something working, I took one of the sample files included in the package and modified to my needs. It works so long as I'm not using namespaces, and that is my question. How can I get around the namespace problem? I don't really care to use it, but it exists in my xml, so I either have to use it or ignore it. Either solution is fine.
Anyway, here is my starter code. It doesn't do anything but take an xpath query try to use it against the hard coded xml doc.
public static void main(String[] args) {
String query = args[0];
File XMLStream=null;
String xmlFileName="doc.xml";
OutputStream destStream=System.out;
XQueryExpression exp=null;
Configuration C=new Configuration();
C.setSchemaValidation(false);
C.setValidation(false);
StaticQueryContext SQC=new StaticQueryContext(C);
DynamicQueryContext DQC=new DynamicQueryContext(C);
QueryProcessor processor = new QueryProcessor(SQC);
Properties props=new Properties();
try{
exp=processor.compileQuery(query);
XMLStream=new File(xmlFileName);
InputSource XMLSource=new InputSource(XMLStream.toURI().toString());
SAXSource SAXs=new SAXSource(XMLSource);
DocumentInfo DI=SQC.buildDocument(SAXs);
DQC.setContextNode(DI);
SequenceIterator iter = exp.iterator(DQC);
while(true){
Item i = iter.next();
if(i != null){
System.out.println(i.getStringValue());
}
else break;
}
}
catch (Exception e){
System.err.println(e.getMessage());
}
}
An example XML file is here...
<?xml version="1.0"?>
<ns1:animal xmlns:ns1="http://my.catservice.org/">
<cat>
<catId>8889</catId>
<fedStatus>true</fedStatus>
</cat>
</ns1:animal>
If I run this with a query including the namespace, I get an error. For example:
/ns1:animal/cat/ gives the error: "Prefix ns1 has not been declared".
If I remove the ns1: from the query, it gives me nothing. If I doctor the xml to remove the "ns1:" prepended to "animal" I can run the query /animal/cat/ with success.
Any help would be greatly appreciated. Thanks.
Error message correctly points out that your xpath expression does not indicate what namespace prefix "ns1" means (binds to). Just because document to operate on happens to use binding for "ns1" does not mean it is what should be used: this because in XML, it's the namespace URI that matters, and prefixes are just convenient shortcuts to the real thing.
So: how do you define the binding? There are 2 generic ways; either provide a context that can resolve the prefix, or embed actual URI within XPath expression.
Regarding the first approach, this email from Saxon author mentions JAXP method XPath.setNamespaceContext(), similarly, Jaxen XPath processor FAQ has some sample code that could help
That's not very convenient, as you have to implement NamespaceContext, but once you have an implementation you'll be set.
So the notation approach... let's see: Top Ten Tips to Using XPath and XPointer shows this example:
to match element declared with namespace like:
xmlns:book="http://my.example.org/namespaces/book"
you use XPath name like:
{http://my.example.org/namespaces/book}section
which hopefully is understood by Saxon (or Jaxen).
Finally, I would recommend upgrading to Saxon9 if possible, if you have any trouble using one of above solutions.
If you want to have something working out of the box, you can check out embedding-xquery-in-java. There's github project, which uses Saxon to evaluate some sample XQuery expressions.
Regards