In this question I asked about supporting an expression language and used the Javascript idea sucessfully Putting a simple expression language into java
But the Javascript expressions required have become quite verbose and Im trying to work out how I can use ScriptEngine to create javascript functions that I can refer to in my expressions so that the expressions can be shorter.
So far I've hacked a solution by using reexp on the user entered string which can include a pseudo function called ifempty which I then convert to the javascript before passing to script engine
public final String formatFromMask(String mask,Song exampleSong)
{
mask = convertPsuedoFunctions(mask);
try
{
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
for(SongFieldName next:SongFieldName.values())
{
engine.put(next.getScriptVar(),exampleSong.getFieldValueOrEmptyString(next.getSongFieldKey()));
}
Object result = engine.eval(mask);
return (String)result;
}
catch(ScriptException se)
{
se.printStackTrace();
}
return "";
}
private String convertPsuedoFunctions(String mask)
{
//i.e ifnotempty(artist,' - ') -> (artist.length>0 ? artist + ' - ' : '')
mask=mask.replaceAll("ifnotempty\\(([a-z]*)\\,('.*')\\)",
"($1.length>0 ? $1 + $2 : '')");
return mask;
}
which could parse an expression such as
ifnotempty(album,'/')
+ ifnotempty(artist,' - ')
+ ifnotempty(album,' - ')
+ ifnotempty(track,' - ')
+ ifnotempty(title,'')
but I was wondering about a proper solution, whereby I actually create a real javascript function.
Why not creating a real Javascript function that you add to the script?
function ifnotempty(value,sep){
return value != undefined && value.length > 0 ? value + sep : '';
}
So your function becomes:
private String convertPsuedoFunctions(String mask)
{
return
"function ifnotempty(value,sep){return value!=undefined&&value.length>0?value+sep:'';}"
+ mask;
}
Additionally you can create a file with some default functions you support and prepend that to the users script. Just like above. But instead of one hardcoded function, you read the file into a String.
private static final String defaultFunctions =
com.google.common.io.Files.toString(new File("functions.js"),Charsets.US_ASCII);
private String convertPsuedoFunctions(String mask)
{
return defaultFunctions + mask;
}
Related
I have a php code as shown below which validates the answer at Line A which user enters in a html form.
When user enters any answer with apostrophe in the html input field form, I am getting the error message Secret Answer is Invalid.
For example: On entering Hello World', I am getting the error message Secret Answer is Invalid from Line Z.
//response
$response_error = new error();
$response_error->field = SECRET_response;
if($response != "" && $service->validAnswer($answer) != 'true'){ // Line A
$response_error->inError = true;
$response_error->errorMessage = SECRET_response.ISINVALID; // Line Z
} else {
$response_error->inError = false;
}
The Java code/method belonging to the validAnswer method used at Line A above is:
public static boolean validAnswer(String answer) {
Pattern a = Pattern.compile("^(?=.*\\S)[a-zA-Z0-9éèàêâçîëïÇÉÔÂÊÎÔÛËÏÀùÙ!#%&$%*\\- ]+$"); // Line B
Matcher b = a.matcher(answer);
logger.info("validAnswer: mmatches(): " + (b.matches()) + " a: " + a);
return b.matches();
}
Problem Statement:
I am wondering what changes I need to make in the java code above so that it takes apostrophe in the html input form.
This is what I have tried in the Java code:
I have put ' in at the end of [ ] inside of it. On trying that, it doesn't seem to work.
public static boolean validAnswer(String answer) {
Pattern a = Pattern.compile("^(?=.*\\S)[a-zA-Z0-9éèàêâçîëïÇÉÔÂÊÎÔÛËÏÀùÙ!#%&$%*\\-' ]+$"); // Line A
Matcher b = a.matcher(answer);
logger.info("validAnswer: mmatches(): " + (b.matches()) + " a: " + a);
return b.matches();
}
Calling Java from PHP just to use a regex is very weird and inefficient. PHP has regex support of course, so you don't need Java for that.
Anyway, your latest code works perfectly:
import java.util.regex.*;
public class Test
{
public static boolean validAnswer(String answer)
{
Pattern a = Pattern.compile("^(?=.*\\S)[a-zA-Z0-9éèàêâçîëïÇÉÔÂÊÎÔÛËÏÀùÙ!#%&$%*\\-' ]+$");
Matcher b = a.matcher(answer);
return b.matches();
}
public static void main(String args[])
{
System.out.println(validAnswer("Hello World'"));
}
}
Output:
true
So I guess you didn't recompile your code after modifying it.
I have URLs as below and need to trim them as follows without the last segment. There may or may not be a trailing slash.
localhost:8080/myapp -> localhost:8080/
https://myapp-dev.myhost.com/app/ -> https://myapp-dev.myhost.com/
https://myapp-dev.myhost.com/app/app2 -> https://myapp-dev.myhost.com/app/
Of course I could try solutions like
String[] tokens = uri.split("/"); // then concatenate previous ones...
or
Path path = Paths.get(uri.getPath());
String secondToLast = path.getName(path.getNameCount() - 2).toString();
But isn't there some more robust utility or method?
Try passing the url string into a URL object and then pulling out the required segments:
URL someURL = new URL("https://myapp-dev.myhost.com/app/");
System.out.println("PATH = " + someURL.getPath());
System.out.println("HOST = " + someURL.getHost());
System.out.println("PROTOCOL = " + someURL.getProtocol());
System.out.println("PORT = " + someURL.getPort());
output:
PATH = /app/
HOST = myapp-dev.myhost.com
PROTOCOL = https
PORT = 8080
If all you need is to trim everything after the last "/" (or the second last if the string ends with "/") may be a simple function could solve this:
public static void main(String[] args){
Function<String,String> trimUrlString = s -> {
s = s.endsWith("/") ? s.substring(0, s.length()-1) : s;
return s.substring(0, s.lastIndexOf('/')+1);
};
String u1 = "localhost:8080/myapp";
System.out.println(trimUrlString.apply(u1));
String u2 = "https://myapp-dev.myhost.com/app/";
System.out.println(trimUrlString.apply(u2));
}
//output: localhost:8080/ https://myapp-dev.myhost.com/
EDIT
Another aproach which might be shorter is to chain two replaceAll calls :
myString.replaceAll("/$", "").replaceAll("/[^/]+$", "/");
The first call will remove a forward slash at the end if any, if there is no slash at the end myString remains the same. The second call will then replace every char after the last / which is not a /
Some test cases with your examples:
String[] urls = {"localhost:8080/myapp",
"https://myapp-dev.myhost.com/app/test.pdf",
"http://myapp-dev.host.com/app/",
"http://app.host.com:8080/app/app2"};
for(String url : urls){
String s = url.replaceAll("/$", "").replaceAll("/[^/]+$", "/");
System.out.println(url);
System.out.println(s);
System.out.println();
}
You can split the string using a regular expression as I have mentioned in the comment.
I provide below the Regex.
^https?:\/\/\w+(:[0-9]*)?(\.\w+)?
You can try with the following examples.
https://mydomain:8080
http://localhost:8090
You can also verify in https://rubular.com/ by pasting the regular expression and the example strings.
Use String.lastIndexOf and String.substring to strip off last component.
Something like:
private String stripLastComponent(String path) {
int n = path.lastIndexOf('/');
if(n < 0) { // no / in path
return path;
}
String stripped = path.substring(0, n);
if(n == path.length()) { // '/' was last char, so try stripping again
stripped = stripLastComponent(stripped);
}
return stripped;
}
Please let me know how to get youtube ID without going to regular expression?
Using above method following URL, didn't work
http://www.youtube.com/e/dQw4w9WgXcQ
http://www.youtube.com/watch?feature=player_embedded&v=dQw4w9WgXcQ
public static String extractYTId(String youtubeUrl) {
String video_id = "";
try {
if(youtubeUrl != null && youtubeUrl.trim().length() > 0 && youtubeUrl.startsWith("http")) {
String expression = "^.*((youtu.be" + "\\/)" + "|(v\\/)|(\\/u\\/w\\/)|(embed\\/)|(watch\\?))\\??v?=?([^#\\&\\?]*).*"; // var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
//String expression = "^.*(?:youtu.be\\/|v\\/|e\\/|u\\/\\w+\\/|embed\\/|v=)([^#\\&\\?]*).*";
CharSequence input = youtubeUrl;
Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(input);
if(matcher.matches()) {
String groupIndex1 = matcher.group(7);
if(groupIndex1 != null && groupIndex1.length() == 11)
video_id = groupIndex1;
}
}
} catch(Exception e) {
Log.e("YoutubeActivity", "extractYTId " + e.getMessage());
}
return video_id;
}
Other links working fine
http://www.youtube.com/v/0zM3nApSvMg?fs=1&hl=en_US&rel=0
http://www.youtube.com/embed/0zM3nApSvMg?rel=0
http://www.youtube.com/watch?v=0zM3nApSvMg&feature=feedrec_grec_index
http://www.youtube.com/watch?v=0zM3nApSvMg
http://youtu.be/0zM3nApSvMg
http://www.youtube.com/watch?v=0zM3nApSvMg#t=0m10s
http://youtu.be/dQw4w9WgXcQ
http://www.youtube.com/embed/dQw4w9WgXcQ
http://www.youtube.com/v/dQw4w9WgXcQ
http://www.youtube.com/watch?v=dQw4w9WgXcQ
http://www.youtube-nocookie.com/v/6L3ZvIMwZFM?version=3&hl=en_US&rel=0
You can use following RegEx
^(?:(?:https?:\/\/)?(?:www\.)?)?(youtube(?:-nocookie)?\.com|youtu\.be)\/.*?(?:embed|e|v|watch\?.*?v=)?\/?([a-z0-9]+)
RegEx Breakup:
^: Start of the line anchor
(?:(?:https?:\/\/)?(?:www\.)?)?:
(?:https?:\/\/)?: Match http:// or https:// optionally
(?:www\.)?)?: Match www. zero or one time
(youtube(?:-nocookie)?\.com|youtu\.be)\/: Match either
youtube.com or youtube-nocookie.com or youtu.be followed by /
.*?: Lazy match. Match until the next pattern satisfies.
(?:embed|e|v|watch\?.*?v=)?\/?:
(?:embed|e|v|watch\?.*?v=)?: Match embed or e or v or from watch? to v= or nothing
\/?: Match / zero or one time
([a-z0-9]+): Match one or more alphanumeric characters and add that in the captured group.
Live DemoUsing JavaScript
var regex = /^(?:(?:https?:\/\/)?(?:www\.)?)?(youtube(?:-nocookie)?\.com|youtu\.be)\/.*?(?:embed|e|v|watch\?.*?v=)?\/?([a-z0-9]+)/i;
// An array of all the youtube URLs
var youtubeLinks = [
'http://www.youtube.com/e/dQw4w9WgXcQ',
'http://www.youtube.com/watch?feature=player_embedded&v=dQw4w9WgXcQ',
'http://www.youtube.com/v/0zM3nApSvMg?fs=1&hl=en_US&rel=0',
'http://www.youtube.com/embed/0zM3nApSvMg?rel=0',
'http://www.youtube.com/watch?v=0zM3nApSvMg&feature=feedrec_grec_index',
'http://www.youtube.com/watch?v=0zM3nApSvMg',
'http://youtu.be/0zM3nApSvMg',
'http://www.youtube.com/watch?v=0zM3nApSvMg#t=0m10s',
'http://youtu.be/dQw4w9WgXcQ',
'http://www.youtube.com/embed/dQw4w9WgXcQ',
'http://www.youtube.com/v/dQw4w9WgXcQ',
'http://www.youtube.com/watch?v=dQw4w9WgXcQ',
'http://www.youtube-nocookie.com/v/6L3ZvIMwZFM?version=3&hl=en_US&rel=0'
];
// An object to store the results
var youtubeIds = {};
// Iterate over the youtube URLs
youtubeLinks.forEach(function(url) {
// Get the value of second captured group to extract youtube ID
var id = "<span class='youtubeId'>" + (url.match(regex) || [0, 0, 'No ID present'])[2] + "</span>";
// Add the URL and the extracted ID in the result object
youtubeIds[url] = id;
});
// Log the object in the browser console
console.log(youtubeIds);
// To show the result on the page
document.getElementById('output').innerHTML = JSON.stringify(youtubeIds, 0, 4);
.youtubeId {
color: green;
font-weight: bold;
}
<pre id="output"></pre>
Your regex is designed for youtu.be domain, of course it doesn't work with youtube.com one.
Construct java.net.URL (https://docs.oracle.com/javase/7/docs/api/java/net/URL.html) from your URL string
Use URL#getQuery() to get the query part
Check Parse a URI String into Name-Value Collection for a ways to decode query part into a name-value map, and get value for name 'v'
If there is no 'query' part (like in http://www.youtube.com/e/dQw4w9WgXcQ), then use URL#getPath() (which will give you /e/dQw4w9WgXcQ) and parse your video ID from it, e. g., by skipping first 3 symbols: url.getPath().substring(3)
Update. Why not regex? Because standard JDK URL parser is much more robust. It is being tested by the whole Java community, while RegExp-based reinvented wheel is only tested by your own code.
I like to use this function for all YouTube video ids. I pass through the url and return only the id. Check the fiddle below.
var ytSrc = function( url ){
var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
var match = url.match(regExp);
if (match&&match[7].length==11){
return match[7];
}else{
alert("Url incorrecta");
}
}
https://jsfiddle.net/keinchy/tL4thwd7/1/
Here i want to validate filename using regex in java. i implemented below code but this is not works for me for 3rd type file.
Can i check prefix and extenstion in regex ???
My validate filename looks like these 3 ways
1) prefix_digit.digit.extenstion example : AB_1.1.fuij (Here fuij is my extension)
2) prefix_digit.digit.digit.extenstion example : AB_1.1.1.fuij
3) prefix_digit.digit.B/P.digit.extensionexample : AB_1.1.B.1.fuij
Only these 3 types of file valid. 3rd one is beta and pilot version files. if beta and pilot version file is there than is should be like this which i mentioned above
I am going to write some valid and invalid files
**Valid :**
AB_1.1.fuij
AB_1.4.fuij
AB_1.1.1.fuij
AB_1.1.B.1.fuij
AB_3.4.P.7.fuij
***Invalid :***
AB_0.1.fuij
AB_1.B.1.1.fuij(B/P should be place on 3rd always)
AB_1.2.B.0.fuij
CODE :
import java.util.ArrayList;
import java.util.regex.Pattern;
public class democlass {
/**
* Test harness.
*/
public static void main(String[] args) {
ArrayList<String> demoversion = new ArrayList<String>();
System.out.println("Result >>>>>>>>>>>> "
+isFileValid("AB_1.1.fuij"));
System.out.println("Result >>>>>>>>>>>> "
+isFileValid("AB_1.B.fuij"));
System.out.println("Result >>>>>>>>>>>> "
+isFileValid("AB_1.1.1.fuij"));
System.out.println("Result >>>>>>>>>>>> "
+isFileValid("AB_1.P.1.1.fuij"));
System.out.println("Result >>>>>>>>>>>> "
+isFileValid("AB_1.1.B.1.fuij"));
}
private static boolean isFileValid(String input)
{
String regexFinalBugFix = "^\\d+\\.\\d+\\.\\d+$";
String regexFinal = "^\\d+\\.\\d+$";
String regexBetaPilot = "^\\d+\\.\\d+\\.\\[BP]+\\.\\d+$";
final Pattern pattern1 = Pattern.compile(regexFinal);
final Pattern pattern2 = Pattern.compile(regexBetaPilot);
final Pattern pattern3 = Pattern.compile(regexFinalBugFix);
String inputVersion = null;
int suffixIndex = input.lastIndexOf(".");
int prefixIndex = input.lastIndexOf("_");
if (suffixIndex > 0 && prefixIndex > 0) {
inputVersion = input.substring(prefixIndex + 1,
suffixIndex);
String prefixString1 = input.substring(0, 3);
String suffixString1 = input.substring(suffixIndex);
if(prefixString1.equals("AB_") && suffixString1.equals(".fuij"))
{
if (pattern1.matcher(inputVersion).matches()
|| pattern2.matcher(inputVersion).matches()
|| pattern3.matcher(inputVersion).matches()) {
return true;
}
return false;
}
return false;
}
return false;
}
}
OUTPUT :
Result >>>>>>>>>>>> true
Result >>>>>>>>>>>> false
Result >>>>>>>>>>>> true
Result >>>>>>>>>>>> false
Result >>>>>>>>>>>> false : It should be valid but it is false, why??
Your regexBetaPilot is wrong: you are escaping the opening bracket of the [BP] class. Try this instead:
String regexBetaPilot = "^\\d+\\.\\d+\\.[BP]+\\.\\d+$";
You can easily combine all three patterns into a single pattern:
String regex = "\\d+\\.(\\d+\\.([BP]+\\.)?)?\\d+";
You don't need the anchors (^ and $). Since you are using matches() instead of find(), it will always try to match the entire string.
EDIT I left in the + after [BP] because that's what you had in your original code. However, if you want to match a single B or P, then you should remove the + from the pattern.
You are escaping the opening bracket of [BP], so it tries to find a [ in the string.
This works:
String regexBetaPilot = "^\\d+\\.\\d+\\.[BP]+\\.\\d+$";
Something like this should work with AB being static:
Regular Expression: AB_\d+\.\d+((\.\d){0,1}|\.[BP]\.\d+)\.fuij
as a Java string AB_\\d+\\.\\d+((\\.\\d){0,1}|\\.[BP]\\.\\d+)\\.fuij
This misses two of your listed invalids, but I was unsure why they should be invalid. I can halep more if you explain the rules for success / failure better?
You can simplify your regular expression to
AB_\d+\.\d+(?:(?:\.[BP])?\.\d+)?\.fuij
This matches AB_digits.digits. Then comes an optional .digits, .B.digits or .P.digits. And finally matches .fuij. From your examples, there might be only a single B or P. If you wish to match multiple Bs and Ps, just add the + again.
And then your isFileValid() function might be reduced to
private static boolean isFileValid(String input)
{
final String re = "AB_\\d+\\.\\d+(?:(?:\\.[BP])?\\.\\d+)?\\.fuij";
final Pattern pattern = Pattern.compile(re);
return pattern.matcher(input).matches();
}
I have a Big html in String variable and I want to get contents of a div. I can not rely on regular expression because it can have nested div's. So, let's suppose I have following String -
String test = "<div><div id=\"mainContent\">foo bar<div>good best better</div> <div>test test</div></div><div>foo bar</div></div>";
Then how can I get this with a simple java program -
<div id="mainContent">foo bar<div>good best better</div> <div>test test</div></div>
Well my approch is something like this (might be horrable, still fighting to correct) -
public static void main(String[] args) {
int count = 1;
int fl = 0;
String s = "<div><div id=\"mainContent\">foo bar<div>good best better</div> <div>test test</div></div><div>foo bar</div></div>";
String tmp = s;
int len = s.length();
for (int i=0; i<len; i++){
int st = s.indexOf("div>");
if(st > -1) {
char c = s.charAt(st-1);
if(c == '/') {
count--;
} else {
count++;
}
s = s.substring(st+4);
System.out.println(s);
i = i + st;
System.out.println(c + " -- " + st + " -- " + count + " -- " + i);
if (count == 0) {
fl = i;
break;
}
}
}
System.out.println("final ind - " + fl);
s = tmp.substring(0, fl + 4);
System.out.println("final String - " + s);
}
I would recommend using JSoup to parse the HTML and find what you are looking for.
It fulfills the simple requirement for sure. You can do what you want in just a couple of lines of code!
jsoup is a Java library for working with real-world HTML. It provides
a very convenient API for extracting and manipulating data, using the
best of DOM, CSS, and jquery-like methods.
jsoup implements the WHATWG HTML5 specification, and parses HTML to
the same DOM as modern browsers do.
scrape and parse HTML from a URL, file, or string
find and extract data, using DOM traversal or CSS selectors
jsoup is designed to deal with all varieties of HTML found in the
wild; from pristine and validating, to invalid tag-soup; jsoup will
create a sensible parse tree.
Using the selector syntax makes finding and extracting data extremely simple.
public static void main(final String[] args)
{
final String s = "<div><div id=\"mainContent\">foo bar<div>good best better</div> <div>test test</div></div><div>foo bar</div></div>";
final Document d = Jsoup.parse(s);
final Elements e = d.select("#mainContent");
System.out.println(e.get(0));
}
outputs
<div id="mainContent">
foo bar
<div>
good best better
</div>
<div>
test test
</div>
</div>
Doesn't get much more simple than that!
I'm afraid the answer is: You don't. At least not with a "simple" program...
But there is hope: You can use a HTML parser library (like NekoHTML or HTMLParser, although the latter project seems to be dead) to parse the string and retrive the part you need.