View Javadoc

1   package eu.scape_project.watch.rest;
2   
3   import com.sun.jersey.api.client.ClientResponse;
4   import com.sun.jersey.api.client.GenericType;
5   import com.sun.jersey.api.client.UniformInterfaceException;
6   import com.sun.jersey.api.client.WebResource;
7   import com.sun.jersey.api.client.WebResource.Builder;
8   import eu.scape_project.watch.domain.AsyncRequest;
9   import eu.scape_project.watch.domain.Entity;
10  import eu.scape_project.watch.domain.EntityType;
11  import eu.scape_project.watch.domain.Property;
12  import eu.scape_project.watch.domain.PropertyValue;
13  import eu.scape_project.watch.domain.RequestTarget;
14  import eu.scape_project.watch.utils.KBUtils;
15  import eu.scape_project.watch.utils.exception.NotFoundException;
16  
17  import java.util.List;
18  
19  import javax.ws.rs.core.MediaType;
20  
21  import thewebsemantic.binding.RdfBean;
22  
23  /**
24   * Client for Watch REST service.
25   * 
26   * @author Luis Faria <lfaria@keep.pt>
27   * 
28   */
29  public class WatchClient {
30    // private final Logger log = LoggerFactory.getLogger(WatchClient.class);
31  
32    /**
33     * Separator between the resource and the format.
34     */
35    private static final String FS = ".";
36  
37    /**
38     * Separator between the resource and the arguments.
39     */
40    private static final String AS = "/";
41  
42    /**
43     * Special word that allows listing of a resource.
44     */
45    private static final String LIST = "list";
46  
47    /**
48     * Query key to define a listing start index.
49     */
50    private static final String START = "start";
51  
52    /**
53     * Query key to define a listing maximum number of items.
54     */
55    private static final String MAX = "max";
56  
57    /**
58     * Query key to define a listing filtered by Entity Type.
59     */
60    private static final String TYPE = "type";
61  
62    /**
63     * Query key to define a listing filtered by query.
64     */
65    private static final String QUERY = "query";
66  
67    /**
68     * Jersey web resource connection.
69     */
70    private final WebResource resource;
71  
72    /**
73     * Output format to use.
74     */
75    private final Format format;
76  
77    /**
78     * The format of the output.
79     * 
80     * @author Luis Faria <lfaria@keep.pt>
81     * 
82     */
83    public static enum Format {
84      /**
85       * Use JSON as output format.
86       */
87      JSON,
88      /**
89       * Use XML as output format.
90       */
91      XML;
92  
93      @Override
94      public String toString() {
95        return super.toString().toLowerCase();
96      }
97  
98      /**
99       * Helper method to get related MediaType.
100      * 
101      * @return The related MediaType or <code>null</code> if not applicable
102      */
103     public String getMediaType() {
104       if (this.equals(JSON)) {
105         return MediaType.APPLICATION_JSON;
106       } else if (this.equals(XML)) {
107         return MediaType.APPLICATION_XML;
108       } else {
109         return null;
110       }
111     }
112   }
113 
114   /**
115    * Create a new Watch client.
116    * 
117    * @param resource
118    *          the jersey web resource to use
119    * @param format
120    *          the output format to use
121    */
122   public WatchClient(final WebResource resource, final Format format) {
123     super();
124     this.resource = resource;
125     this.format = format;
126   }
127 
128   /**
129    * Create a new {@link Entity}.
130    * 
131    * @param name
132    *          the entity name
133    * @param type
134    *          the name of the entity type
135    * @return the created entity
136    */
137   public Entity createEntity(final String name, final String type) {
138     return this.resource.path(KBUtils.ENTITY + FS + this.format + AS + name).accept(this.format.getMediaType())
139       .post(Entity.class, type);
140   }
141 
142   /**
143    * Get entity from server.
144    * 
145    * @param name
146    *          the entity name
147    * @return the entity with that name or <code>null</code> if not found
148    */
149   public Entity getEntity(final String name) {
150     try {
151       return this.resource.path(KBUtils.ENTITY + FS + this.format + AS + name).accept(this.format.getMediaType())
152         .get(Entity.class);
153     } catch (final UniformInterfaceException e) {
154       final ClientResponse resp = e.getResponse();
155       if (resp.getStatus() == NotFoundException.CODE) {
156         return null;
157       } else {
158         throw e;
159       }
160     }
161   }
162 
163   /**
164    * Update the entity defined by the name.
165    * 
166    * @param name
167    *          the name of the entity to update
168    * @param entity
169    *          the updated entity that will replace the previous one
170    * @return the updated entity after merged with the knowledge base
171    */
172   public Entity updateEntity(final String name, final Entity entity) {
173     return this.resource.path(KBUtils.ENTITY + FS + this.format + AS + name).accept(this.format.getMediaType())
174       .put(Entity.class, entity);
175   }
176 
177   /**
178    * List all entities in the knowledge base.
179    * 
180    * @return the complete list of entities.
181    */
182   public List<Entity> listEntity(int start, int max) {
183     return listEntity(null, start, max);
184   }
185 
186   public List<Entity> listEntity(String type, int start, int max) {
187     return (List<Entity>) this.resource.path(KBUtils.ENTITY + FS + this.format + AS + LIST)
188       .queryParam(TYPE, type != null ? type : "").queryParam(START, Integer.toString(start))
189       .queryParam(MAX, Integer.toString(max)).accept(this.format.getMediaType()).get(new GenericType<List<Entity>>() {
190       });
191   }
192 
193   /**
194    * Delete an entity.
195    * 
196    * @param name
197    *          the name of the entity to delete.
198    * @return the deleted entity.
199    */
200   public Entity deleteEntity(final String name) {
201     return this.resource.path(KBUtils.ENTITY + FS + this.format + AS + name).accept(this.format.getMediaType())
202       .delete(Entity.class);
203   }
204 
205   /**
206    * Create a new entity type.
207    * 
208    * @param name
209    *          a unique name to identify this entity type
210    * @param description
211    *          the entity type description
212    * @return the newly created entity type
213    */
214   public EntityType createEntityType(final String name, final String description) {
215     return this.resource.path(KBUtils.ENTITY_TYPE + FS + this.format + AS + name).accept(this.format.getMediaType())
216       .post(EntityType.class, description);
217   }
218 
219   /**
220    * Get an entity type.
221    * 
222    * @param name
223    *          the entity type name
224    * @return the {@link EntityType} or <code>null</code> if not found
225    */
226   public EntityType getEntityType(final String name) {
227     try {
228       return this.resource.path(KBUtils.ENTITY_TYPE + FS + this.format + AS + name).accept(this.format.getMediaType())
229         .get(EntityType.class);
230     } catch (final UniformInterfaceException e) {
231       final ClientResponse resp = e.getResponse();
232       if (resp.getStatus() == NotFoundException.CODE) {
233         return null;
234       } else {
235         throw e;
236       }
237     }
238   }
239 
240   /**
241    * Update an existing entity type.
242    * 
243    * @param name
244    *          the existing entity type name
245    * @param entity
246    *          the new entity type that should replace the old one
247    * @return the updated entity type
248    */
249   public EntityType updateEntityType(final String name, final EntityType entity) {
250     return this.resource.path(KBUtils.ENTITY_TYPE + FS + this.format + AS + name).accept(this.format.getMediaType())
251       .put(EntityType.class, entity);
252   }
253 
254   /**
255    * List all existing entity types.
256    * 
257    * @return A complete list of entity types in the KB.
258    */
259   public List<EntityType> listEntityType() {
260     return (List<EntityType>) this.resource.path(KBUtils.ENTITY_TYPE + FS + this.format + AS + LIST)
261       .accept(this.format.getMediaType()).get(new GenericType<List<EntityType>>() {
262       });
263   }
264 
265   /**
266    * Delete an existing entity type.
267    * 
268    * @param name
269    *          the name of the entity type to delete
270    * @return the deleted entity type
271    */
272   public EntityType deleteEntityType(final String name) {
273     return this.resource.path(KBUtils.ENTITY_TYPE + FS + this.format + AS + name).accept(this.format.getMediaType())
274       .delete(EntityType.class);
275   }
276 
277   /**
278    * Create a new {@link Property}.
279    * 
280    * @param type
281    *          the {@link EntityType} related with this property
282    * @param name
283    *          a unique name (within this entity type) to identity this property
284    * @param description
285    *          the property description
286    * @return the newly created property
287    */
288   public Property createProperty(final String type, final String name, final String description) {
289     return this.resource.path(KBUtils.PROPERTY + FS + this.format + AS + type + AS + name)
290       .accept(this.format.getMediaType()).post(Property.class, description);
291   }
292 
293   /**
294    * Get an existing property.
295    * 
296    * @param type
297    *          the name of the {@link EntityType} related to this property
298    * @param name
299    *          the name of this property within the {@link EntityType}
300    * @return the {@link Property} or <code>null</code> if not found.
301    */
302   public Property getProperty(final String type, final String name) {
303     try {
304       return this.resource.path(KBUtils.PROPERTY + FS + this.format + AS + type + AS + name)
305         .accept(this.format.getMediaType()).get(Property.class);
306     } catch (final UniformInterfaceException e) {
307       final ClientResponse resp = e.getResponse();
308       if (resp.getStatus() == NotFoundException.CODE) {
309         return null;
310       } else {
311         throw e;
312       }
313     }
314   }
315 
316   /**
317    * Update an existing property.
318    * 
319    * @param type
320    *          the {@link EntityType} related to this property
321    * @param name
322    *          the name of this property within the {@link EntityType}
323    * @param property
324    *          the new update property
325    * @return the updated Property after merging with the KB.
326    */
327   public Property updateProperty(final String type, final String name, final Property property) {
328     return this.resource.path(KBUtils.PROPERTY + FS + this.format + AS + type + AS + name)
329       .accept(this.format.getMediaType()).put(Property.class, property);
330   }
331 
332   /**
333    * List all properties in the KB.
334    * 
335    * @return A complete list of all properties in the KB
336    */
337   public List<Property> listProperty() {
338     return (List<Property>) this.resource.path(KBUtils.PROPERTY + FS + this.format + AS + LIST)
339       .accept(this.format.getMediaType()).get(new GenericType<List<Property>>() {
340       });
341   }
342 
343   /**
344    * Delete an existing property.
345    * 
346    * @param type
347    *          the {@link EntityType} related to this property
348    * @param name
349    *          the name of this property within the {@link EntityType}
350    * @return The deleted property.
351    */
352   public Property deleteProperty(final String type, final String name) {
353     return this.resource.path(KBUtils.PROPERTY + FS + this.format + AS + type + AS + name)
354       .accept(this.format.getMediaType()).delete(Property.class);
355     // TODO treat the not found exception
356   }
357 
358   /**
359    * Create a new {@link PropertyValue}.
360    * 
361    * @param entity
362    *          The {@link Entity} related to this property value
363    * @param property
364    *          the {@link Property} related to this property value
365    * @param value
366    *          the value of the related property for the related entity.
367    * @return the newly created {@link PropertyValue}
368    */
369   public PropertyValue createPropertyValue(final String entity, final String property, final String value) {
370     return this.resource.path(KBUtils.PROPERTY_VALUE + FS + this.format + AS + entity + AS + property)
371       .accept(this.format.getMediaType()).post(PropertyValue.class, value);
372   }
373 
374   /**
375    * Get an existing {@link PropertyValue}.
376    * 
377    * @param entity
378    *          The {@link Entity} related to this property value
379    * @param property
380    *          the {@link Property} related to this property value
381    * @return the {@link PropertyValue} or <code>null</code> if not found.
382    */
383   public PropertyValue getPropertyValue(final String entity, final String property) {
384     try {
385       return this.resource.path(KBUtils.PROPERTY_VALUE + FS + this.format + AS + entity + AS + property)
386         .accept(this.format.getMediaType()).get(PropertyValue.class);
387     } catch (final UniformInterfaceException e) {
388       final ClientResponse resp = e.getResponse();
389       if (resp.getStatus() == NotFoundException.CODE) {
390         return null;
391       } else {
392         throw e;
393       }
394     }
395   }
396 
397   /**
398    * Update an existing {@link PropertyValue}.
399    * 
400    * @param entity
401    *          The {@link Entity} related to this property value
402    * @param property
403    *          the {@link Property} related to this property value
404    * @param value
405    *          The updated value of the related {@link Property} to the related
406    *          {@link Entity}
407    * @return the updated {@link PropertyValue}
408    */
409   public PropertyValue updatePropertyValue(final String entity, final String property, final String value) {
410     return this.resource.path(KBUtils.PROPERTY_VALUE + FS + this.format + AS + entity + AS + property)
411       .accept(this.format.getMediaType()).put(PropertyValue.class, value);
412   }
413 
414   /**
415    * List all property values in the KB.
416    * 
417    * @return the complete list of property values in the KB
418    */
419   public List<PropertyValue> listPropertyValue() {
420     return (List<PropertyValue>) this.resource.path(KBUtils.PROPERTY_VALUE + FS + this.format + AS + LIST)
421       .accept(this.format.getMediaType()).get(new GenericType<List<PropertyValue>>() {
422       });
423   }
424 
425   /**
426    * Delete an existing property value.
427    * 
428    * @param entity
429    *          The {@link Entity} related to this property value
430    * @param property
431    *          the {@link Property} related to this property value
432    * @return the deleted property value.
433    */
434   public PropertyValue deletePropertyValue(final String entity, final String property) {
435     return this.resource.path(KBUtils.PROPERTY_VALUE + FS + this.format + AS + entity + AS + property)
436       .accept(this.format.getMediaType()).delete(PropertyValue.class);
437     // TODO treat the not found exception
438   }
439 
440   /**
441    * Make a synchronous request query.
442    * 
443    * @param <T>
444    *          A class that must extends RdfBean and should be related to
445    *          possible targets of a request.
446    * @param targetClass
447    *          The query target class, that will define the resource type.
448    * @param query
449    *          The SPARQL query bindings.
450    * @param start
451    *          The index of the first item to retrieve.
452    * @param max
453    *          The maximum number of items to retrieve.
454    * @return The list of resources of the type defined by target, filtered by
455    *         the constraints above.
456    */
457   @SuppressWarnings("unchecked")
458   public <T extends RdfBean<T>> List<T> getRequest(final Class<T> targetClass, final String query, final int start,
459     final int max) {
460 
461     final RequestTarget target = RequestTarget.getTargetByClass(targetClass);
462 
463     final Builder builder = this.resource.path(KBUtils.SYNC_REQUEST + FS + this.format + AS + target)
464       .queryParam(QUERY, query).queryParam(START, Integer.toString(start)).queryParam(MAX, Integer.toString(max))
465       .accept(this.format.getMediaType());
466 
467     List<? extends RdfBean<?>> ret;
468     switch (target) {
469       case ENTITY_TYPE:
470         ret = builder.get(new GenericType<List<EntityType>>() {
471         });
472         break;
473       case PROPERTY:
474         ret = builder.get(new GenericType<List<Property>>() {
475         });
476         break;
477       case ENTITY:
478         ret = builder.get(new GenericType<List<Entity>>() {
479         });
480         break;
481       case PROPERTY_VALUE:
482         ret = builder.get(new GenericType<List<PropertyValue>>() {
483         });
484         break;
485       default:
486         ret = null;
487         break;
488     }
489 
490     // return this.resource.path(KB.SYNC_REQUEST + FS + this.format + AS +
491     // target).queryParam(QUERY, query)
492     // .queryParam(START, Integer.toString(start)).queryParam(MAX,
493     // Integer.toString(max))
494     // .accept(this.format.getMediaType()).get(new
495     // GenericType<List<T>>(targetClass));
496     return (List<T>) ret;
497   }
498 
499   /**
500    * Create a new async request.
501    * 
502    * @param request
503    *          The new async request to insert into the KB.
504    * @return The created async request after merging with the KB
505    */
506   public AsyncRequest createAsyncRequest(final AsyncRequest request) {
507     return this.resource.path(KBUtils.ASYNC_REQUEST + FS + this.format).accept(this.format.getMediaType())
508       .post(AsyncRequest.class, request);
509   }
510 }