1 /***
2 *
3 * The owl-s matcher software is subject to the GNU Lesser General
4 * Public License Version 2.1 (the "License"). You may not copy or use this
5 * file, in either source code or executable form, except in compliance
6 * with the License. You may obtain a copy of the License at
7 * http://www.fsf.org/licenses/lgpl.txt or http://www.opensource.org/.
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied without
11 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 * PURPOSE. See the License for the specific language governing rights and
13 * limitations under the License.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this distribution; if not, write to the
17 *
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307 USA
21 *
22 * Copyright (C) 2003-2004
23 * TU Berlin, FG IVS
24 * Stefan Tang,
25 * Christoph Liebetruth,
26 * Michael C. Jaeger,
27 *
28 * More information available at http://ivs.tu-berlin.de/
29 *
30 * $Id$
31 *
32 */
33 package de.tuberlin.ivs.owl.service;
34
35 import org.jdom.input.SAXBuilder;
36 import org.jdom.*;
37 import org.jdom.xpath.*;
38 import java.util.*;
39 import de.tuberlin.ivs.owl.matching.Reasoner;
40 import java.net.URL;
41 import java.io.PrintStream;
42 import java.io.IOException;
43 import java.net.MalformedURLException;
44 import java.net.ConnectException;
45
46 /***
47 * Parses a OWL-S service description into the representation classes
48 * of a OWL Service.
49 *
50 * @author Stefan Tang (steftang@stanford.edu), Christoph Liebetruth (christophl@voelcker.com)
51 * @version 1.1
52 */
53 public class OwlsParser
54 {
55
56 /***
57 * Default constructor.
58 * @param out The stream that output information is written to.
59 */
60 public OwlsParser(PrintStream out)
61 {
62 outWriter = out;
63 }
64
65 /***
66 * The service namespace.
67 */
68 public static Namespace serviceNamespace = Namespace.getNamespace("http://www.daml.org/services/owl-s/1.0/Service.owl#");
69
70 /***
71 * The RDF namespace.
72 */
73 public static Namespace rdfNamespace = Namespace.getNamespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
74
75 /***
76 * The profile namespace.
77 */
78 public static Namespace profileNamespace = Namespace.getNamespace("http://www.daml.org/services/owl-s/1.0/Profile.owl#");
79
80
81 /***
82 * The ID of the concept Profile as of OWL-S 1.0
83 */
84 public static String profileID = "http://www.daml.org/services/owl-s/1.0/Profile.owl#Profile";
85
86 /***
87 * The stream that output information is written to.
88 */
89 private PrintStream outWriter;
90
91
92 /***
93 * Searches the main Xml-File for a service:Service tag and returns its rdfID as a parser entry point
94 * @param path The uri to the main xml
95 * @return a service rdfID or null if not found
96 */
97 private String GetServiceID( URL path )
98 {
99 try
100 {
101 SAXBuilder builder = new SAXBuilder();
102 Document doc = null;
103 doc = builder.build( path );
104 Element root = doc.getRootElement();
105 XPath xpath = XPath.newInstance( "//service:Service" );
106 xpath.addNamespace( "service", OwlsParser.serviceNamespace.getURI() );
107 Element serviceNode = (Element) xpath.selectSingleNode( root );
108 if ( serviceNode != null )
109 {
110 String id = serviceNode.getAttributeValue( "ID", OwlsParser.rdfNamespace );
111 return( id );
112 }
113 return( null );
114 }
115 catch (Exception e)
116 {
117 return( null );
118 }
119 }
120
121
122 /***
123 * Parses a OWL-S service descriptions.
124 * @param path The URL of the OWL-S file. Note that this file has
125 * to be the organizational entry point of the service descriptions (i.e. the
126 * root file that contains the <service> tag elements).
127 * @param reasoner An instance of the reasoner that represents the knowledge
128 * base.
129 * @return The parsed service.
130 */
131 public Service parse(URL path, Reasoner reasoner) throws OwlsParseException
132 {
133 Service service = new Service();
134 try
135 {
136 reasoner.loadOwlFile( path );
137 }
138 catch (java.net.ConnectException ce)
139 {
140 throw new OwlsParseException("A remote OWL file could not be opened.\n." +
141 ce.getMessage());
142 }
143 String serviceID = this.GetServiceID( path );
144 if ( serviceID == null )
145 {
146 throw new OwlsParseException("Could not find any service ID. Please make sure at least one\n" +
147 "<service:Service> element is present and has corresponding namespace\n" +
148 serviceNamespace.getURI());
149 }
150
151
152 service.setID( serviceID );
153
154 List profiles = reasoner.GetPresentedProfileIDs( service.getID() );
155 if (profiles==null)
156 {
157 throw new OwlsParseException("Could not find any profile. Please make sure at least one\n" +
158 "<service:presents> element is present and has corresponding namespace\n" +
159 serviceNamespace.getURI());
160 }
161
162 Iterator iter = profiles.iterator();
163 while(iter.hasNext())
164 {
165 String profileResourceID = (String) iter.next();
166 String profilepath = profileResourceID.substring( 0, profileResourceID.lastIndexOf( "#" ) );
167 String profileID = profileResourceID.substring( profileResourceID.lastIndexOf( "#" ) + 1 );
168 Profile profile = this.parseProfile( profileID, profileResourceID, reasoner );
169 profile.setService( service );
170 service.addProfile( profile );
171 }
172 return( service );
173 }
174
175 /***
176 * Parses a OWL-S profile.
177 * @param profileID The ID of the profile to parse, as a OWL file
178 * can contain several profiles.
179 * @param profileResourceID The ID of the profile to parse (including namespace uri) for querying
180 * the reasoner
181 * @param reasoner An instance of the reasoner that represents the knowledge
182 * base.
183 * @return a parsed profile including inputs, outputs, preconditions, effects and actors (contact information)
184 */
185 private Profile parseProfile( String profileID, String profileResourceID, Reasoner reasoner ) throws OwlsParseException
186 {
187 Profile profile = new Profile();
188 writeLog("Parsing profile " + profileID);
189
190 profile.setID( profileID );
191 profile.setTextDescription( reasoner.GetProfileTextDescription( profileResourceID ) );
192 profile.setServiceName( reasoner.GetProfileServiceName( profileResourceID ) );
193 profile.setClassName( reasoner.GetRdfType( profileResourceID ) );
194
195 List contacts = reasoner.GetProfileContactInformationIDs( profileResourceID );
196 Iterator contactIter = contacts.iterator();
197 while ( contactIter.hasNext() )
198 {
199 String contactID = (String) contactIter.next();
200 Actor actor = this.ParseActor( contactID, reasoner );
201 profile.addContactInformation( actor );
202 }
203
204 List inputs = reasoner.GetProfileInputIDs( profileResourceID );
205 Iterator inputIter = inputs.iterator();
206 while ( inputIter.hasNext() )
207 {
208 String rdfID = (String) inputIter.next();
209 Input input = new Input();
210 String rdfType = reasoner.GetRdfType( rdfID );
211 input.setPropertyName( rdfType.substring( rdfType.lastIndexOf( "#" ) + 1 ) );
212 input.setRefersTo( rdfID );
213 input.setRestrictedTo( reasoner.getPropertyType( input.getRefersTo() ) );
214 profile.addInput( input );
215
216 }
217
218 List outputs = reasoner.GetProfileOutputIDs( profileResourceID );
219 Iterator outputIter = outputs.iterator();
220 while ( outputIter.hasNext() )
221 {
222 String rdfID = (String) outputIter.next();
223 String rdfType = reasoner.GetRdfType( rdfID );
224 Output output = new Output();
225 output.setPropertyName( rdfType.substring( rdfType.lastIndexOf( "#" ) + 1 ) );
226 output.setRefersTo( rdfID );
227 output.setRestrictedTo( reasoner.getPropertyType( output.getRefersTo() ) );
228 profile.addOutput(output);
229 }
230
231 List preconditions = reasoner.GetProfilePreconditionIDs( profileResourceID );
232 Iterator preconditionIter = preconditions.iterator();
233 while ( preconditionIter.hasNext() )
234 {
235 String rdfID = (String) preconditionIter.next();
236 String rdfType = reasoner.GetRdfType( rdfID );
237 Output output = new Output();
238 output.setPropertyName( rdfType.substring( rdfType.lastIndexOf( "#" ) + 1 ) );
239 output.setRefersTo( rdfID );
240 output.setRestrictedTo( reasoner.getPropertyType( output.getRefersTo() ) );
241 profile.addOutput(output);
242 }
243
244 List effects = reasoner.GetProfileEffectIDs( profileResourceID );
245 Iterator effectIter = effects.iterator();
246 while ( effectIter.hasNext() )
247 {
248 String rdfID = (String) effectIter.next();
249 String rdfType = reasoner.GetRdfType( rdfID );
250 Effect effect = new Effect();
251 effect.setPropertyName( rdfType.substring( rdfType.lastIndexOf( "#" ) + 1 ) );
252 effect.setRefersTo( rdfID );
253 effect.setRestrictedTo( reasoner.getPropertyType( effect.getRefersTo() ) );
254 profile.addEffect( effect );
255 }
256
257 return( profile );
258 }
259
260
261
262
263
264 /***
265 * Parses an actor class.
266 * @param actorResourceID the rdfResourceID of the actor including namespace uri for querying the reasoner
267 * @param reasoner reasoner.
268 * @return The parsed Actor.
269 */
270 private Actor ParseActor( String actorResourceID, Reasoner reasoner )
271 {
272 Actor actor = new Actor();
273 String actorID = actorResourceID.substring( actorResourceID.lastIndexOf( "#" ) + 1 );
274 actor.setID( actorID );
275 actor.setName( reasoner.GetActorName( actorResourceID ) );
276 actor.setTitle( reasoner.GetActorTitle( actorResourceID ) );
277 actor.setPhone( reasoner.GetActorPhone( actorResourceID ) );
278 actor.setFax( reasoner.GetActorFax( actorResourceID ) );
279 actor.setEmail( reasoner.GetActorEMail( actorResourceID ) );
280 actor.setPhysicalAddress( reasoner.GetActorPhysicalAddress( actorResourceID ) );
281 actor.setWebURL( reasoner.GetActorWebUrl( actorResourceID ) );
282 return( actor );
283 }
284
285
286 /***
287 * Writes a message to the output stream if the stream is initialized.
288 * @param message The message to be written.
289 */
290 private void writeLog( String message )
291 {
292 if ( outWriter != null )
293 {
294 outWriter.println( message );
295 }
296 }
297 }