001 /**
002 * Copyright (C) 2007-2011, Jens Lehmann
003 *
004 * This file is part of DL-Learner.
005 *
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program. If not, see <http://www.gnu.org/licenses/>.
018 */
019
020 package org.dllearner.kb.sparql;
021 import java.util.Iterator;
022 import java.util.Set;
023
024 import org.apache.log4j.Logger;
025 import org.dllearner.algorithms.gp.ADC;
026 import org.dllearner.core.ComponentManager;
027 import org.dllearner.core.AbstractReasonerComponent;
028 import org.dllearner.core.owl.Constant;
029 import org.dllearner.core.owl.DatatypeExactCardinalityRestriction;
030 import org.dllearner.core.owl.DatatypeMaxCardinalityRestriction;
031 import org.dllearner.core.owl.DatatypeMinCardinalityRestriction;
032 import org.dllearner.core.owl.DatatypeSomeRestriction;
033 import org.dllearner.core.owl.DatatypeValueRestriction;
034 import org.dllearner.core.owl.Description;
035 import org.dllearner.core.owl.DescriptionVisitor;
036 import org.dllearner.core.owl.Entity;
037 import org.dllearner.core.owl.Individual;
038 import org.dllearner.core.owl.Intersection;
039 import org.dllearner.core.owl.NamedClass;
040 import org.dllearner.core.owl.Negation;
041 import org.dllearner.core.owl.Nothing;
042 import org.dllearner.core.owl.ObjectAllRestriction;
043 import org.dllearner.core.owl.ObjectExactCardinalityRestriction;
044 import org.dllearner.core.owl.ObjectMaxCardinalityRestriction;
045 import org.dllearner.core.owl.ObjectMinCardinalityRestriction;
046 import org.dllearner.core.owl.ObjectOneOf;
047 import org.dllearner.core.owl.ObjectProperty;
048 import org.dllearner.core.owl.ObjectSomeRestriction;
049 import org.dllearner.core.owl.ObjectValueRestriction;
050 import org.dllearner.core.owl.Thing;
051 import org.dllearner.core.owl.Union;
052 import org.dllearner.parser.KBParser;
053 import org.dllearner.parser.ParseException;
054
055 /**
056 * Converter from DL-Learner descriptions to a corresponding natural
057 * language description.
058 *
059 * @author Sebastian Knappe
060 *
061 *
062 */
063 public class NaturalLanguageDescriptionConvertVisitor implements DescriptionVisitor{
064
065 private static Logger logger = Logger.getLogger(ComponentManager.class);
066
067 private String query="";
068
069 private AbstractReasonerComponent service;
070
071 public NaturalLanguageDescriptionConvertVisitor(AbstractReasonerComponent service)
072 {
073 //stack.push("subject");
074 this.service=service;
075 }
076
077 private String getDescription()
078 { // for old function see below
079 // it was using the object attribute in a strange way
080 // QUALITY: what if this function is called several times?? should be private maybe?
081 String tmpQuery=""+query;
082
083 query = tmpQuery;
084 return query;
085 }
086
087 public static String getNaturalLanguageDescription(Description description, AbstractReasonerComponent service)
088 {
089 NaturalLanguageDescriptionConvertVisitor visitor=new NaturalLanguageDescriptionConvertVisitor(service);
090 description.accept(visitor);
091 String ret = visitor.getDescription();
092 return ret;
093 }
094
095 public static String getNaturalLanguageDescription(String descriptionKBSyntax, AbstractReasonerComponent service) throws ParseException
096 {
097 Description d = KBParser.parseConcept(descriptionKBSyntax);
098 NaturalLanguageDescriptionConvertVisitor visitor=new NaturalLanguageDescriptionConvertVisitor(service);
099 d.accept(visitor);
100 String ret = visitor.getDescription();
101 return ret;
102 }
103
104 private String getLabelFromReasoner(Entity ent)
105 {
106 String label;
107 // try{
108 Set<Constant> set=service.getLabel(ent);
109 if (set.size()>0){
110 Iterator<Constant> iter=set.iterator();
111 label=iter.next().getLiteral();
112 }
113 else label="";
114 // }
115 // catch (ReasoningMethodUnsupportedException e)
116 // {
117 // label="";
118 // }
119
120 return label;
121 }
122
123 /**
124 * Used for testing the Sparql Query converter.
125 *
126 * @param args
127 */
128 public static void main(String[] args) {
129 try {
130 /*SortedSet<String> s = new TreeSet<String>();
131 HashMap<String,String> result = new HashMap<String,String>();
132 String conj="(\"http://dbpedia.org/class/yago/Person100007846\" AND \"http://dbpedia.org/class/yago/Head110162991\")";
133 s.add("EXISTS \"http://dbpedia.org/property/disambiguates\".TOP");
134 s.add("EXISTS \"http://dbpedia.org/property/successor\".\"http://dbpedia.org/class/yago/Person100007846\"");
135 s.add("EXISTS \"http://dbpedia.org/property/successor\"."+conj);
136 s.add("ALL \"http://dbpedia.org/property/disambiguates\".TOP");
137 s.add("ALL \"http://dbpedia.org/property/successor\".\"http://dbpedia.org/class/yago/Person100007846\"");
138 s.add("\"http://dbpedia.org/class/yago/Person100007846\"");
139 s.add(conj);
140 s.add("(\"http://dbpedia.org/class/yago/Person100007846\" OR \"http://dbpedia.org/class/yago/Head110162991\")");
141 s.add("NOT \"http://dbpedia.org/class/yago/Person100007846\"");
142 s.add("(\"http://dbpedia.org/class/yago/HeadOfState110164747\" AND (\"http://dbpedia.org/class/yago/Negotiator110351874\" AND \"http://dbpedia.org/class/yago/Representative110522035\"))");
143 for (String kbsyntax : s) {
144 result.put(kbsyntax,NaturalLanguageDescriptionConvertVisitor.getNaturalLanguageDescription(kbsyntax,"DBPEDIA"));
145 }
146 System.out.println("************************");
147 for (String string : result.keySet()) {
148 System.out.println("KBSyntayString: "+string);
149 System.out.println("Query:\n"+result.get(string));
150 System.out.println("************************");
151 }
152 System.out.println("Finished");*/
153 //String conj="EXISTS \"http://xmlns.com/foaf/0.1/page\".<= 0 \"http://www.w3.org/2004/02/skos/core#subject\".TOP";
154 //String conj="(\"Male\" AND (\"hasDog\" = 18))";
155 // ObjectValueRestriction rest=new ObjectValueRestriction(new ObjectProperty("hasAge"),new Individual("18"));
156 //System.out.println(NaturalLanguageDescriptionConvertVisitor.getNaturalLanguageDescription(rest));
157 } catch (/*Parse*/Exception e) {
158 // TODO Auto-generated catch block
159 e.printStackTrace();
160 }
161 }
162
163 /* (non-Javadoc)
164 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.Negation)
165 */
166 public void visit(Negation description) {
167 logger.trace("Negation");
168 query+="not ";
169 description.getChild(0).accept(this);
170 }
171
172 /* (non-Javadoc)
173 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.ObjectAllRestriction)
174 */
175 public void visit(ObjectAllRestriction description) {
176 logger.trace("ObjectAllRestriction");
177 String label=getLabelFromReasoner((ObjectProperty)description.getRole());
178 if (label.length()>0) query+="all "+label+" are ";
179 else query+="all "+description.getRole().toString().substring(description.getRole().toString().lastIndexOf("/")+1)+" are ";
180 description.getChild(0).accept(this);
181 logger.trace(description.getRole().toString());
182 logger.trace(description.getChild(0).toString());
183 }
184
185 /* (non-Javadoc)
186 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.ObjectSomeRestriction)
187 */
188 public void visit(ObjectSomeRestriction description) {
189 logger.trace("ObjectSomeRestriction");
190 String label=getLabelFromReasoner((ObjectProperty)description.getRole());
191 if (label.length()>0) query+="has "+label+" which is ";
192 else query+="has "+description.getRole().toString().substring(description.getRole().toString().lastIndexOf("/")+1)+" which is ";
193 description.getChild(0).accept(this);
194 logger.trace(description.getRole().toString());
195 logger.trace(description.getChild(0).toString());
196 }
197
198 /* (non-Javadoc)
199 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.Nothing)
200 */
201 public void visit(Nothing description) {
202 logger.trace("Nothing");
203 if (query.endsWith("which is ")) query=query.substring(0, query.length()-10);
204 if (query.endsWith("are ")) query=query.substring(0, query.length()-5);
205 if (query.endsWith("and ")) query=query.substring(0, query.length()-5);
206 if (query.endsWith("or ")) query=query.substring(0, query.length()-4);
207 //query+="nothing";
208 }
209
210 /* (non-Javadoc)
211 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.Thing)
212 */
213 public void visit(Thing description) {
214 logger.trace("Thing");
215 if (query.endsWith("which is ")) query=query.substring(0, query.length()-10);
216 if (query.endsWith("are ")) query=query.substring(0, query.length()-5);
217 if (query.endsWith("and ")) query=query.substring(0, query.length()-5);
218 if (query.endsWith("or ")) query=query.substring(0, query.length()-4);
219 //query+="anything";
220 }
221
222 /* (non-Javadoc)
223 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.Intersection)
224 */
225 public void visit(Intersection description) {
226 // HACK see replace hacks in other functions
227 logger.trace("Intersection");
228 description.getChild(0).accept(this);
229 query+=" and ";
230 description.getChild(1).accept(this);
231 }
232
233 /* (non-Javadoc)
234 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.Union)
235 */
236 public void visit(Union description) {
237 // HACK see replace hacks in other functions
238 logger.trace("Union");
239 description.getChild(0).accept(this);
240 query+=" or ";
241 description.getChild(1).accept(this);
242 }
243
244 /* (non-Javadoc)
245 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.ObjectMinCardinalityRestriction)
246 */
247 public void visit(ObjectMinCardinalityRestriction description) {
248 logger.trace("ObjectMinCardinalityRestriction");
249 if (query.endsWith("which is ")) query=query.substring(0, query.length()-3)+"has ";
250 query+="at least "+description.getCardinality()+" "+description.getRole().toString()+" which is ";
251 description.getChild(0).accept(this);
252 }
253
254 /* (non-Javadoc)
255 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.ObjectExactCardinalityRestriction)
256 */
257 public void visit(ObjectExactCardinalityRestriction description) {
258 logger.trace("ObjectExactCardinalityRestriction");
259 if (query.endsWith("which is ")) query=query.substring(0, query.length()-3)+"has ";
260 query+="exactly "+description.getCardinality()+" "+description.getRole().toString()+" which is ";
261 description.getChild(0).accept(this);
262 }
263
264 /* (non-Javadoc)
265 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.ObjectMaxCardinalityRestriction)
266 */
267 public void visit(ObjectMaxCardinalityRestriction description) {
268 logger.trace("ObjectMaxCardinalityRestriction");
269 if (query.endsWith("which is ")) query=query.substring(0, query.length()-3)+"has ";
270 query+="at most "+description.getCardinality()+" "+description.getRole().toString()+" which is ";
271 description.getChild(0).accept(this);
272 }
273
274 /* (non-Javadoc)
275 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.ObjectValueRestriction)
276 */
277 public void visit(ObjectValueRestriction description) {
278 ObjectProperty op = (ObjectProperty) description.getRestrictedPropertyExpression();
279 Individual ind = description.getIndividual();
280 String label=getLabelFromReasoner(ind);
281 String indLabel;
282 if (label.length()>0)
283 indLabel =label;
284 else
285 indLabel =ind.getName();
286 label=getLabelFromReasoner(op);
287 String propLabel;
288 if (label.length()>0)
289 propLabel =label;
290 else
291 propLabel =op.getName();
292 query += propLabel + " is " + indLabel;
293 }
294
295 /* (non-Javadoc)
296 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.DatatypeValueRestriction)
297 */
298 public void visit(DatatypeValueRestriction description) {
299 logger.trace("DatatypeValueRestriction");
300 //if (query.endsWith("which is ")) query=query.substring(0, query.length()-3)+"has ";
301 query+=description.getRestrictedPropertyExpression().toString()+" has the value "+description.getValue();
302 }
303
304 /* (non-Javadoc)
305 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.NamedClass)
306 */
307 public void visit(NamedClass description) {
308
309 logger.trace("NamedClass");
310 if (description.getName().equals("http://dbpedia.org/class/yago/Entity100001740")) {
311 if (query.endsWith("which is ")) query=query.substring(0, query.length()-10);
312 if (query.endsWith("are ")) query=query.substring(0, query.length()-5);
313 if (query.endsWith("and ")) query=query.substring(0, query.length()-5);
314 if (query.endsWith("or ")) query=query.substring(0, query.length()-4);
315 }
316 //SortedSet<String> label=tasks.queryAsSet("SELECT ?label WHERE {<"+description.getName()+"> <http://www.w3.org/2000/01/rdf-schema#label> ?label}", "label");
317 String l=getLabelFromReasoner(description);
318 String l2=description.getName().substring(description.getName().lastIndexOf("/")+1, description.getName().length()).replace('_', ' ');
319 if ((l.length()==0)||(l.length()+5<l2.length()&&!l2.matches(".*[0-9]"))) l=l2;
320
321 //replacements
322 l=l.replaceAll("Cities", "City");
323 l=l.replaceAll("Players", "Player");
324
325 l=l.replaceAll("([^-\040])([A-Z])([^A-Z])", "$1 $2$3");
326
327 if (l.toLowerCase().startsWith("a")||l.toLowerCase().startsWith("e")||l.toLowerCase().startsWith("i")||l.toLowerCase().startsWith("o")||l.toLowerCase().startsWith("u")) query+="an "+l;
328 else query+="a "+l;
329 }
330
331
332
333 /* (non-Javadoc)
334 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.algorithms.gp.ADC)
335 */
336 public void visit(ADC description) {
337 logger.trace("ADC");
338 }
339
340 /* (non-Javadoc)
341 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.DatatypeMinCardinalityRestriction)
342 */
343 public void visit(DatatypeMinCardinalityRestriction description) {
344 logger.trace("DatatypeMinCardinalityRestriction");
345 }
346
347 /* (non-Javadoc)
348 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.DatatypeExactCardinalityRestriction)
349 */
350 public void visit(DatatypeExactCardinalityRestriction description) {
351 logger.trace("DatatypeExactCardinalityRestriction");
352 }
353
354 /* (non-Javadoc)
355 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.DatatypeMaxCardinalityRestriction)
356 */
357 public void visit(DatatypeMaxCardinalityRestriction description) {
358 logger.trace("DatatypeMaxCardinalityRestriction");
359 }
360
361 /* (non-Javadoc)
362 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.DatatypeSomeRestriction)
363 */
364 public void visit(DatatypeSomeRestriction description) {
365 logger.trace("DatatypeSomeRestriction");
366 }
367
368 /* (non-Javadoc)
369 * @see org.dllearner.core.owl.DescriptionVisitor#visit(org.dllearner.core.owl.ObjectOneOf)
370 */
371 @Override
372 public void visit(ObjectOneOf description) {
373 logger.trace("ObjectOneOf");
374 }
375 }