Pull string from RDF node - java

Im trying to get the data in a more readable format when using a SPARQL query with Jena, however I have no idea how to extract the data in a proper way.
As for now, the output is:
"http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#SaucelitoCanyon"
Where instead would like to just have the "SaucelitoCanyon" as a output.
public JenaQuery() {
String wineRegion = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
+ "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
+ "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\n"
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
+ "PREFIX wine:<http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#>\n"
+ "SELECT ?region ?winery \n"
+ "WHERE {?wine wine:locatedIn ?region . \n"
+ "?region wine:locatedIn wine:CaliforniaRegion . \n"
+ "?wine wine:hasMaker ?winery}";
String inputFileName = "wine.rdf";
// create an empty model
Model model = ModelFactory.createDefaultModel();
// use the FileManager to find the input file
InputStream in;
in = FileManager.get().open(inputFileName);
if (in == null) {
throw new IllegalArgumentException(
"File: " + inputFileName + " not found");
}
// read the RDF/XML file
model.read(in, null);
try (QueryExecution qexec = QueryExecutionFactory.create(wineRegion, model)) {
ResultSet results = qexec.execSelect();
while (results.hasNext()) {
QuerySolution row = results.next();
RDFNode winery = row.get("winery");
System.out.println(winery);
}
qexec.close();
}
}

Since you've already got the prefix in the SPARQL query, you can use the strafter and str functions to convert the URIs to strings and take the suffix after the prefix. In the following, I've used values ?winery { ... } to bind ?winery to a particular URI, but your query already takes care of that. The important part is the bind afterward that takes care of the string processing.
PREFIX wine: <http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#>
SELECT ?winery ?localname
WHERE {
values ?winery { wine:SomeWinery }
bind( strafter(str(?winery),str(wine:)) as ?localname )
}
winery localname
<http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#SomeWinery> "SomeWinery"
That said, in well structured ontologies, individuals will often have an rdfs:label that should provide a string label for an individual. When it's available, you might consider simply retrieving that value. E.g.,
SELECT ?winery ?name
WHERE {
#-- ...
?winery rdfs:label ?name
}
This was previously described in my answer to retrieving the class name of a specific subclass in owl, but that question didn't involve Jena, so it's not quite a duplicate, even though the same SPARQL-based solution works.

Note that in Jena you have two nice Java sources for nice qName conversions: Prologue and PrefixMapping. Your Model is a PrefixMapping and your Query (if you compiled it) is a Prologue. Both of these objects have a #shortForm(String uri) method that you can use to get a shortened form of a URI without modifying your query.
If your model has prefixes defined in it, you can use PrefixMapping#shortForm(String) as follows (pseudocode):
final Model m = // TODO
final String shortForm = m.shortForm(winery.asResource().getURI());
If you compile your Query using QueryFactory, then you can use query-specific prefixes in Prologue#shortForm(String) as follows (pseudocode):
final Query q = QueryFactory.create(/* TODO */);
final String shortForm = q.shortForm(winery.asResource().getURI());
It's then worth knowing that this will give you a name of the form wine:SaucelitoCanyon (if the wine: prefix is defined, otherwise it will give you http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#SaucelitoCanyon). You would still need to split the resulting string to get just the local name which may be a little verbose:
final String longName = winery.asResource().getURI();
final String localName;
if( !shortForm.equals(longName) ) {
localName = shortForm.split(":")[1];
}
else {
throw new IllegalStateException("could not resolve prefix for "+longName);
}
This provides you a guarantee that you are using the local name associated with some prefix in your model or your query.

You can use the "getLocalName" function in Jena. That will get you the local name of the resource, which is what you seem to be looking for:
QuerySolution row = results.next();
RDFNode winery = row.get("winery");
String r = winery.asNode().getLocalName();
System.out.println(r);
Alternatively you can get the node as a resource directly, which saves you one line of code:
String r = row.getResource("winery").getLocalName();
Edit: as stated in the comments below, this answer will only be valid if your prefix "wine" is as you have declared it in your code. Otherwise the results may not be as desired.

Related

jpa containing query with list

I have a table Called Media that has a column "tagList" of type List. I want to search media based on list of input tag.
I need a method like this.
List<Media> findByTagListContaining(<List> inputTagList);
This gives error but
List<Media> findByTagListContaining(String inputTag);
works fine. How to make first one works. I need partial matching as well for example if any row has tagList ["mentos","bollywood","comedy"]
and inputTagList is ["men","boll"] that row should come in result.
Hello, You can try this.
{
List<String> inputTagList = new ArrayList<String>();
inputTagList.add("men");
inputTagList.add("boll");
findByTagListContaining(inputTagList);
}
call your find By Tag List method
List<Media> findByTagListContaining(List<String> inputTagList){
String inputTagString = "[";
for(String strTemp : inputTagList){
//here create you own pattern matching code. Ex:
inputTagString+= "'" + strTemp + "%'" + ",";
}
inputTagString+="%]";
//And your inputTagString is ready to match you element ["mentos","bollywood","comedy"]
}

Java Hard Coded SQL Query works but the exact same query read from a file buffer fails

I am using Java and MySQL. This code works and returns the expected results:-
queryStr = "SELECT PROGRAM, EQUIPMENT, t.PART_NUMBER, SN, GFE_CAP, t.STATUS, ii.Part_Number, ii.Serial_Number, [Inventory_Type – Level 1], ii.Status, ii.Destination, ii.Location" +
" FROM tblGFE_CAP as t, NGC_BJ_DEV.dbo.ISSUE_ITEMS as ii" +
" WHERE (t.PART_NUMBER = ii.Part_Number)" +
" AND (SN = ii.SERIAL_NUMBER)" +
" AND (GFE_CAP != [Inventory_Type – Level 1])" +
" AND NOT (([Inventory_Type – Level 1] = 'GFP') and (GFE_CAP = 'GFE'))" +
" AND NOT ((ii.Status = 'Retired') AND (t.Status = 'INACTIVE-REPLACED/RETIRED/DISPOSITION'))" +
" AND NOT ((ii.Status = 'Consumed') and (t.Status = 'INACTIVE-REPLACED/RETIRED/DISPOSITION'))" +
" GROUP BY PROGRAM, EQUIPMENT, t.PART_NUMBER, SN, GFE_CAP, t.Status, ii.Part_Number, ii.Serial_Number, [Inventory_Type – Level 1], ii.Destination, ii.Location, ii.Status" +
" ORDER BY GFE_CAP, t.PART_NUMBER, SN";
stmt = con.prepareStatement(queryStr);
rs = stmt.executeQuery();
However, if I read the exact same text from a file (as below) and copy the results into queryStr, the code chokes on the Inventory_Type - Level 1 column name. I confirmed that the resultant strings are identical when passed to preparedStatement. I understand that special characters are not a good idea for the column name, but that is beyond my control.
I cannot change the column name. My real question is why the hard coded query works but the file read does not. Alternatively if there is a syntax that can be used to capture the column name within the java built query string.
String bStr = "";
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader(in.getAbsolutePath()));
while (true)
{
bStr = br.readLine();
if (bStr == null)
break;
sb.append(bStr);
}
br.close();
queryStr = sb.toString();
stmt = con.prepareStatement(queryStr);
rs = stmt.executeQuery();
Use sb.append(bStr).append("\n") instead of sb.append(bStr).
Your current code lose line breaks and probably two different words from adjusting lines become one.
This issue has to do with the fact that you are trying to read in special characters (in this case brackets) using your buffered reader. That problem has already been addressed.
see the following approaches:
Read/write .txt file with special characters
Read special characters in java with BufferedReader

Parse a plain text into a Java Object

I´m parsing a plain text and trying to convert into an Object.
The text looks like(and i can´t change the format):
"N001";"2014-08-12-07.11.37.352000";" ";"some#email.com ";4847 ;"street";"NAME SURNAME ";26 ;"CALIFORNIA ";21
and The Object to convert:
String index;
String timestamp;
String mail;
Integer zipCode
...
I´ve tried with:
StringTokenizer st1 = new StringTokenizer(N001\";\"2014-08-12-07.11.37.352000\";\" \";\"some#email.com \";4847 ;\"street\";\"NAME SURNAME \";26 ;\"CALIFORNIA \";21);
while(st2.hasMoreTokens()) {
System.out.println(st2.nextToken(";").replaceAll("\"",""));
}
And the output is the correct one, i´ve thinking to have a counter and hardcoding with a case bucle and set the field deppending the counter, but the problem is that I have 40 fields...
Some idea?
Thanks a lot!
String line = "N001";"2014-08-12-07.11.37.352000";" ";"some#email.com ";4847 ;"street";"NAME SURNAME ";26 ;"CALIFORNIA ";21
StringTokenizer st1 = new StringTokenizer(line, ";");
while(st2.hasMoreTokens()) {
System.out.println(st2.nextToken().replaceAll("\"",""));
}
Or you can use split method and directly get a array of values using the delimiter ;
String []values = line.split(";");
then iterate through the array and get and cast the values they way you want
Regardless of the way you are parsing the file, you somehow need to define the mapping of column-to-field (and how to parse the text).
if this is a CVS file, you could use a library like super-csv. All you need to do is write a mapping definition.
I would first split your input String based on the semi-colon separator, then clean up the values.
For instance:
String input = "\"N001\";\"2014-08-12-07.11.37.352000\";\" " +
"\";\"some#email.com " +
"\";4847 ;\"street\";\"NAME " +
"SURNAME \";26 ;\"CALIFORNIA " +
"\";21 ";
// raw split
String[] split = input.split(";");
System.out.printf("Raw: %n%s%n", Arrays.toString(split));
// cleaning up whitespace and double quotes
ArrayList<String> cleanValues = new ArrayList<String>();
for (String s: split) {
String clean = s.replaceAll("[\\s\"]", "");
if (!clean.isEmpty()) {
cleanValues.add(clean);
}
}
System.out.printf("Clean: %n%s%n", cleanValues);
Output
Raw:
["N001", "2014-08-12-07.11.37.352000", " ", "some#email.com ", 4847 , "street", "NAME SURNAME ", 26 , "CALIFORNIA ", 21 ]
Clean:
[N001, 2014-08-12-07.11.37.352000, some#email.com, 4847, street, NAMESURNAME, 26, CALIFORNIA, 21]
Note
In order to map the values to your variables you will need to know their index in advance, and it will have to be consistent.
Then you can use the get(int i) method to retrieve them from your List - e.g. cleanValues.get(2) will get you the e-mail, etc.
Note (2)
If you do not know the indices in advance or they may vary, then you are in trouble.
You can of course try to get those indices by using regular expressions but I suspect you might end up complicating your life quite a bit.
you can use Java Reflection to automate your process.
Iterate over the fields
Field[] fields = dummyRow.getClass().getFields();
and set your values
SomeClass object = construct.newInstance();
field.set(object , value);

After extracting data from html using a for loop, how do I insert one by one into a database?

I have extracted multiple data from an HTML using Jsoup and now I am trying to insert one by one into a derby db using JDBC on netbeans.
Here is my code:
public String nameOf() {
String nameStr = null;
String nameResults = "";
for(int j=100;j<=110;j++) {
refNum = j;
//System.out.println("Reference Number: " + refNum);
try {
//crawl and parse HTML from definition and causes page
Document docDandC = Jsoup.connect("http://www.abcd.edu/encylopedia/article/000" + refNum + ".htm").get();
// scrape name data
Elements name = docDandC.select("title");
nameStr = name.get(0).text();
//System.out.println(nameStr);
nameResults += nameStr + " ";
} catch (Exception e) {
//System.out.println("Reference number " + refNum + " does not exist.");
}
}
return nameResults;
So this method takes the names of diseases from 10 different HTMLs. What I am trying to do is to insert one name at a time to a derby db that I have created using JDBC. I have everything set up and all I have left to do is to insert each name in the corresponding name field of a table named DISEASE (which has fields: id, name, etc).
nameResults += nameStr + " ";
This part worries me as well since some diseases can have multiple words. Maybe I should use a list of some sort?
Please help! Thanks in advance.
Something like:
public List<String> nameOf() {
...
List<String> nameResults = new ArrayList<String>();
...
nameResults.add(nameStr);
...
return nameResults;

How should I get this specific text from str?

I have a lot of strings in database like this : "\\LDDESKTOP\news\1455Bloomberg Document # 180784.txt". I want to get the file name after the last slash.
I do this just in a normal way :
str.substring(str.lastIndexOf("\\")+1)
But it doesn't work because the single slash is used for change meanings. Is there a way in java just like python to tell compiler to regard it as a plain string like this , str=r'.......' .
Or how to change the string to "\\\\LDDESKTOP\\news\\1455Bloomberg Document # 180784.txt". So I can pass it to File Object to read this file.
how should I do this? Or other ways to solve this.
Thanks.
The column named path(varchar(150)) in the news table is like this "\LDDESKTOP\news\1362Bloomberg Document # 180691.txt"
And I do a normal select on the path.
the code :
public List<String> getNewsFileName(String startTime,String endTime) {
List<String> newsFileNames = new ArrayList<String>();
String tableName = ConfigFile.getConfig("configuration.txt","SQLServerTable");
String sql = "select Path from [" + tableName + "] where localtime >= '" + startTime + "' and localtime <= '" + endTime + "'";
try {
if(connection==null) {
InvertedIndex.logger.log(Level.SEVERE, "Database connection has not been initialized");
System.exit(-1);
}
stmt=connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
String path=rs.getString(1);
newsFileNames.add(path);
}
} catch (SQLException e) {
InvertedIndex.logger.log(Level.SEVERE,"Fail to store news");
}
return newsFileNames;
}
You use Escape Sequences to specify certain special characters that also have java properties assigned to them.
In order to print a single backslash character in a string you use a set of 2 backslashes \\.
String string = new String("\\\\LDDESKTOP\\news\\1455Bloomberg Document # 180784.txt");
String str = string.substring(string.lastIndexOf("\\")+1);
System.out.println(str);
This prints
1455Bloomberg Document # 180784.txt
Edit 1:
Once you have the string, you can pass it back using the same escape character.
String string = "\\\\LDDESKTOP\\news\\" + str;
This outputs the original
\\LDDESKTOP\news\1455Bloomberg Document # 180784.txt
Edit 2:
Based on what you asked, in order to transform all single backslashes into double backslashes you must use both the escape sequence and the string "replace" method.
If you have this string:
String string = new String("\\\\LDDESKTOP\\news\\1455Bloomberg Document # 180784.txt");
You need to call this code to "double" every backslash:
String newString = string.replace("\\", "\\\\");
This produces the following:
//Note this is before we print it. This illustrates all the escape sequences.
\\\\\\\\LDDESKTOP\\\\news\\\\1455Bloomberg Document # 180784.txt
The string itself will look like this:
\\\\LDDESKTOP\\news\\1455Bloomberg Document # 180784.txt
this code :
String st = "\\LDDESKTOP\news\1455Bloomberg Document # 180784.txt";
st = st.replace("\n", "\\n");
st = st.replace("\\", "\\\\");
String str = st.substring(st.lastIndexOf("\\")+1);
test it.
"\n" is line break.
Thanks for all the efforts you have made . Finally , I think I have found the answer.
Instead of dealing with the string in java program, I process the string using sql functions directly.
Following is what I do.
SELECT * substring(path,len(path)-charindex('\',reverse(path))+2,charindex('\',reverse(path)))
FROM News
This really does a good job !!

Categories