Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/hp/hpl/jena/ontology/event/OntEventManager.java


1   /*****************************************************************************
2    * Source code information
3    * -----------------------
4    * Original author    Ian Dickinson, HP Labs Bristol
5    * Author email       ian.dickinson@hp.com
6    * Package            Jena 2
7    * Web                http://sourceforge.net/projects/jena/
8    * Created            10-Sep-2003
9    * Filename           $RCSfile: OntEventManager.java,v $
10   * Revision           $Revision: 1.6 $
11   * Release status     $State: Exp $
12   *
13   * Last modified on   $Date: 2005/02/21 12:06:02 $
14   *               by   $Author: andy_seaborne $
15   *
16   * (c) Copyright 2001, 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
17   * [See end of file]
18   *****************************************************************************/
19  
20  // Package
21  ///////////////
22  package com.hp.hpl.jena.ontology.event;
23  
24  
25  
26  // Imports
27  ///////////////
28  import java.util.*;
29  
30  import com.hp.hpl.jena.ontology.*;
31  import com.hp.hpl.jena.rdf.listeners.StatementListener;
32  import com.hp.hpl.jena.rdf.model.*;
33  import com.hp.hpl.jena.vocabulary.*;
34  import com.hp.hpl.jena.vocabulary.OntEventsVocab;
35  
36  
37  /**
38   * <p>
39   * An adapter that translates RDF model-level changes into higher level changes that
40   * are appropriate to ontology users.  The large number of specific events that the
41   * ontology model can produce makes the traditional Java style of listener interface
42   * impractical. Instead, this event manager allows the user to register 
43   * {@linkplain OntEventHandler handlers}, based on command pattern, against specific
44   * {@linkplain OntEventsVocab event types}. 
45   * </p>
46   * <p>
47   * For example, to register a handler for the declaration of an ontology class:
48   * </p>
49   * <pre>
50   * OntModel m = ...
51   * OntEventManager em = m.getEventManager();
52   * em.addHandler( OntEvents.CLASS_DECLARATION,
53   *                new OntEventHandler() {
54   *                    public void action( Resource ev, boolean added,
55   *                                        RDFNode arg0, RDFNode arg1 ) {
56   *                        OntClass c = (OntClass) arg0;
57   *                        if (added) {
58   *                            // class c added to model
59   *                        }
60   *                        else {
61   *                            // class c removed from model
62   *                        }
63   *                    }
64   *                }
65   *              );
66   * </pre>
67   * <p>
68   * This listener acts as an adapter for graph events (i.e. adding and
69   * removing triples), converting them to higher-level ontology events.  This is non-trivial, because
70   * Jena currently doesn't have a means of batching changes so that only consistent
71   * graph states are seen.  For efficiency in non event-using models, this listener
72   * is only attached as a statement listener to the underlying graph when the first
73   * ontology event listener is added.
74   * </p>
75   * 
76   * @author Ian Dickinson, HP Labs
77   *         (<a  href="mailto:Ian.Dickinson@hp.com" >email</a>)
78   * @version CVS $Id: OntEventManager.java,v 1.6 2005/02/21 12:06:02 andy_seaborne Exp $
79   */
80  public class OntEventManager 
81      extends StatementListener
82  {
83      // Constants
84      //////////////////////////////////
85  
86      // Static variables
87      //////////////////////////////////
88  
89      /** Initialisation data for the rdf:type to event type table */
90      private static Object[][] s_rdfTypeInit = {
91          {OntEventsVocab.classDeclaration,                       new ProfileAccessor() {public Resource get(Profile p) {return p.CLASS();} } },
92          {OntEventsVocab.datarangeDeclaration,                   new ProfileAccessor() {public Resource get(Profile p) {return p.DATARANGE();} } }, 
93          {OntEventsVocab.propertyDeclaration,                    new ProfileAccessor() {public Resource get(Profile p) {return p.PROPERTY();} } }, 
94          {OntEventsVocab.objectPropertyDeclaration,             new ProfileAccessor() {public Resource get(Profile p) {return p.OBJECT_PROPERTY();} } }, 
95          {OntEventsVocab.datatypePropertyDeclaration,           new ProfileAccessor() {public Resource get(Profile p) {return p.DATATYPE_PROPERTY();} } }, 
96          {OntEventsVocab.transitivePropertyDeclaration,         new ProfileAccessor() {public Resource get(Profile p) {return p.TRANSITIVE_PROPERTY();} } }, 
97          {OntEventsVocab.symmetricPropertyDeclaration,          new ProfileAccessor() {public Resource get(Profile p) {return p.SYMMETRIC_PROPERTY();} } }, 
98          {OntEventsVocab.functionalPropertyDeclaration,         new ProfileAccessor() {public Resource get(Profile p) {return p.FUNCTIONAL_PROPERTY();} } }, 
99          {OntEventsVocab.inverseFunctionalPropertyDeclaration, new ProfileAccessor() {public Resource get(Profile p) {return p.INVERSE_FUNCTIONAL_PROPERTY();} } }, 
100         {OntEventsVocab.annotationPropertyDeclaration,         new ProfileAccessor() {public Resource get(Profile p) {return p.ANNOTATION_PROPERTY();} } }, 
101         {OntEventsVocab.ontologyPropertyDeclaration,           new ProfileAccessor() {public Resource get(Profile p) {return p.ONTOLOGY_PROPERTY();} } }, 
102         {OntEventsVocab.restrictionDeclaration,                 new ProfileAccessor() {public Resource get(Profile p) {return p.RESTRICTION();} } }, 
103         {OntEventsVocab.allDifferentDeclaration,               new ProfileAccessor() {public Resource get(Profile p) {return p.ALL_DIFFERENT();} } }, 
104         {OntEventsVocab.ontologyDeclaration,                    new ProfileAccessor() {public Resource get(Profile p) {return p.ONTOLOGY();} } }, 
105     };
106     
107     /** Initialisation data for the predicate to event type table */
108     private static Object[][] s_predicateInit = {
109         {OntEventsVocab.intersectionOf,                         new ProfileAccessor() {public Resource get(Profile p) {return p.INTERSECTION_OF();} } }, 
110         {OntEventsVocab.equivalentClass,                        new ProfileAccessor() {public Resource get(Profile p) {return p.EQUIVALENT_CLASS();} } }, 
111         {OntEventsVocab.disjointWith,                           new ProfileAccessor() {public Resource get(Profile p) {return p.DISJOINT_WITH();} } }, 
112         {OntEventsVocab.equivalentProperty,                     new ProfileAccessor() {public Resource get(Profile p) {return p.EQUIVALENT_PROPERTY();} } }, 
113         {OntEventsVocab.sameAs,                                 new ProfileAccessor() {public Resource get(Profile p) {return p.SAME_AS();} } }, 
114         {OntEventsVocab.differentFrom,                          new ProfileAccessor() {public Resource get(Profile p) {return p.DIFFERENT_FROM();} } }, 
115         {OntEventsVocab.distinctMembers,                        new ProfileAccessor() {public Resource get(Profile p) {return p.DISTINCT_MEMBERS();} } }, 
116         {OntEventsVocab.unionOf,                                new ProfileAccessor() {public Resource get(Profile p) {return p.UNION_OF();} } }, 
117         {OntEventsVocab.intersectionOf,                         new ProfileAccessor() {public Resource get(Profile p) {return p.INTERSECTION_OF();} } }, 
118         {OntEventsVocab.complementOf,                           new ProfileAccessor() {public Resource get(Profile p) {return p.COMPLEMENT_OF();} } }, 
119         {OntEventsVocab.oneOf,                                  new ProfileAccessor() {public Resource get(Profile p) {return p.ONE_OF();} } }, 
120         {OntEventsVocab.onProperty,                             new ProfileAccessor() {public Resource get(Profile p) {return p.ON_PROPERTY();} } }, 
121         {OntEventsVocab.allValuesFrom,                         new ProfileAccessor() {public Resource get(Profile p) {return p.ALL_VALUES_FROM();} } }, 
122         {OntEventsVocab.hasValue,                               new ProfileAccessor() {public Resource get(Profile p) {return p.HAS_VALUE();} } }, 
123         {OntEventsVocab.someValuesFrom,                        new ProfileAccessor() {public Resource get(Profile p) {return p.SOME_VALUES_FROM();} } }, 
124         {OntEventsVocab.minCardinality,                         new ProfileAccessor() {public Resource get(Profile p) {return p.MIN_CARDINALITY();} } }, 
125         {OntEventsVocab.maxCardinality,                         new ProfileAccessor() {public Resource get(Profile p) {return p.MAX_CARDINALITY();} } }, 
126         {OntEventsVocab.cardinalityQ,                           new ProfileAccessor() {public Resource get(Profile p) {return p.CARDINALITY_Q();} } }, 
127         {OntEventsVocab.minCardinalityQ,                       new ProfileAccessor() {public Resource get(Profile p) {return p.MIN_CARDINALITY_Q();} } }, 
128         {OntEventsVocab.maxCardinalityQ,                       new ProfileAccessor() {public Resource get(Profile p) {return p.MAX_CARDINALITY_Q();} } }, 
129         {OntEventsVocab.cardinality,                             new ProfileAccessor() {public Resource get(Profile p) {return p.CARDINALITY();} } }, 
130         {OntEventsVocab.inverseOf,                              new ProfileAccessor() {public Resource get(Profile p) {return p.INVERSE_OF();} } }, 
131         {OntEventsVocab.imports,                                 new ProfileAccessor() {public Resource get(Profile p) {return p.IMPORTS();} } }, 
132         {OntEventsVocab.versionInfo,                            new ProfileAccessor() {public Resource get(Profile p) {return p.VERSION_INFO();} } }, 
133         {OntEventsVocab.priorVersion,                           new ProfileAccessor() {public Resource get(Profile p) {return p.PRIOR_VERSION();} } }, 
134         {OntEventsVocab.backwardCompatibleWith,                new ProfileAccessor() {public Resource get(Profile p) {return p.BACKWARD_COMPATIBLE_WITH();} } }, 
135         {OntEventsVocab.incompatibleWith,                       new ProfileAccessor() {public Resource get(Profile p) {return p.INCOMPATIBLE_WITH();} } }, 
136     };
137     
138     
139     // Instance variables
140     //////////////////////////////////
141 
142     /** Map from event types to handlers */
143     private Map m_handlers = new HashMap();
144     
145     /** Map from rdf:type to event type */
146     private Map m_rdfTypeToEventType = new HashMap();
147     
148     /** Map from predicate to event type */
149     private Map m_predicateToEventType = new HashMap();
150     
151     /** Default event handler */
152     private OntEventHandler m_defaultHandler = null;
153     
154     
155     // Constructors
156     //////////////////////////////////
157 
158     /**
159      * <p>Construct an ontology event manager for the given ontology model.
160      * This involves registering adapters for the ontology events corresponding
161      * to the language profile of the given model.</p>
162      * @param m An ontology model 
163      */
164     public OntEventManager( OntModel m ) {
165         Profile p = m.getProfile();
166         initialiseTable( m_rdfTypeToEventType, p, s_rdfTypeInit );
167         initialiseTable( m_predicateToEventType, p, s_predicateInit );
168     }
169     
170     
171     // External signature methods
172     //////////////////////////////////
173 
174     /**
175      * <p>Handle the addition of a statement to the model.</p>
176      * @param s The added statement
177      */
178     public void addedStatement( Statement s ) {
179         processStatement( s, true );
180     }
181     
182     
183     /**
184      * <p>Handle the removal of a statement to the model</p>
185      * @param s The removed statement
186      */
187     public void removedStatement( Statement s ) {
188         processStatement( s, false );
189     }
190     
191     
192     /**
193      * <p>Raise an event to be handled by the attached event handlers.</p>
194      * @param event The resource representing the event type
195      * @param added True if this is an addition to the model, false otherwise
196      * @param source The model that caused the event to be raised
197      * @param arg0 The first argument to the event
198      * @param arg1 The second argument to the event, or null
199      * @param arg2 The third argument to the event, or null
200      */
201     public void raise( Resource event, boolean added, Model source, RDFNode arg0, RDFNode arg1, RDFNode arg2 ) {
202         OntEventHandler h = getHandler( event );
203         if (h != null) {
204             h.action( event, added, source, arg0, arg1, arg2 );
205         }
206         else if (m_defaultHandler != null) {
207             // if no assigned handler, call the default handler
208             m_defaultHandler.action( event, added, source, arg0, arg1, arg2 );
209         }
210     }
211     
212     
213     /**
214      * <p>Add the given handler as the default event handler, which will be invoked if
215      * no other handler is applicable to a given event.</p>
216      * @param handler The event handler object
217      */
218     public void addDefaultHandler( OntEventHandler handler ) {
219         m_defaultHandler = handler;
220     }   
221 
222 
223     /**
224      * <p>Add the given handler as the handler for the given event type, replacing
225      * any existing handler.</p>
226      * @param event The event type to be handled, as a resource
227      * @param handler The event handler object
228      */
229     public void addHandler( Resource event, OntEventHandler handler ) {
230         m_handlers.put( event, handler );
231     }   
232 
233 
234     /**
235      * <p>Add the given handlers as the handler for the given event types, replacing
236      * any existing handlers.</p>
237      * @param handlers An array of pairs, where the first element of each pair
238      * is the resource denoting the event to be handled, and the second is the 
239      * handler object
240      */
241     public void addHandlers( Object[][] handlers ) {
242         for (int i = 0;  i < handlers.length;  ) {
243             Resource r = (Resource) handlers[i][0];
244             OntEventHandler h = (OntEventHandler) handlers[i][1];
245             addHandler( r, h );
246         }
247     }   
248 
249     /**
250      * <p>Answer the event handler for the given event, or null if not defined</p>
251      * @param event An event type to look up
252      * @return The current handler for the event, or null
253      */
254     public OntEventHandler getHandler( Resource event ) {
255         return (OntEventHandler) m_handlers.get( event );
256     }   
257 
258 
259     /**
260      * <p>Answer the default event handler, or null if not defined</p>
261      * @return The default event handler, or null
262      */
263     public OntEventHandler getDefaultHandler() {
264         return m_defaultHandler;
265     }   
266 
267 
268     /**
269      * <p>Remove any existing handler for the given event type.</p>
270      * @param event The event for which the handler is to be removed
271      */
272     public void removeHandler( Resource event ) {
273         m_handlers.remove( event );
274     }   
275 
276 
277     /**
278      * <p>Answer true if there is a defined handler for the given event type.</p>
279      * @param event An event type, as a resource
280      * @return True if there is a defined handler for the event
281      */
282     public boolean hasHandler( Resource event ) {
283         return m_handlers.containsKey( event );
284     }   
285     
286     
287     /**
288      * <p>Answer an iterator over the events that are registered in this
289      * event manager.</p>
290      * @return An iterator over the event types of events that have registered handlers
291      */
292     public Iterator listRegisteredEvents() {
293         return m_handlers.keySet().iterator();
294     }
295     
296     
297     // Internal implementation methods
298     //////////////////////////////////
299 
300     /**
301      * <p>Initialise the given map from static initialisation data. This will be a mapping
302      * that allows us to determine the correct ontology event type for a given triple.</p>
303      * @param map The map to update
304      * @param p An ontology language profile
305      * @param source A table of initialisation data
306      */
307     private void initialiseTable( Map map, Profile p, Object[][] source ) {
308         for (int i = 0;  i < source.length;  i++) {
309             // get the initialisation data from the table
310             Resource evType = (Resource) source[i][0];
311             Resource key = ((ProfileAccessor) source[i][1]).get( p );
312             
313             if (key != null) {
314                 // is defined for this term
315                 map.put( key, evType );
316             }
317         }
318     }
319     
320     
321     /**
322      * <p>Process an incoming added or removed statement to raise the appropriate ontology event.</p>
323      * @param s
324      * @param added
325      */
326     private void processStatement( Statement s, boolean added ) {
327         // first check if this an rdf:type statement
328         if (s.getPredicate().equals( RDF.type )) {
329             // yes - now is it a builtin type?
330             Resource type = s.getResource();
331             Resource evType = (Resource) m_rdfTypeToEventType.get( type );
332             
333             if (evType != null) {
334                 // was a known type, so we know which event to raise
335                 raise( evType, added, s.getModel(), s.getSubject(), null, null );
336             }
337             else {
338                 // must be an individual
339                 raise( OntEventsVocab.individualDeclaration, added, s.getModel(), s.getSubject(), type, null );
340             }
341         }
342         else {
343             // not rdf:type, but may still be a known predicate
344             Property pred = s.getPredicate();
345             Resource evType = (Resource) m_predicateToEventType.get( pred );
346             
347             if (evType != null) {
348                 // was a known predicate, so we know which event to raise
349                 raise( evType, added, s.getModel(), s.getSubject(), s.getObject(), null );
350             }
351             else {
352                 // default - assume user data
353                 raise( OntEventsVocab.userData, added, s.getModel(), s.getSubject(), pred, s.getObject() );
354             }
355         }
356     }
357     
358     
359     //==============================================================================
360     // Inner class definitions
361     //==============================================================================
362 
363     /** Simple wrapper to allow us to dynamically extract elements from the profile */
364     private static interface ProfileAccessor {
365         public Resource get( Profile p );
366     }
367 }
368 
369 
370 /*
371  *  (c) Copyright 2001, 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
372  *  All rights reserved.
373  *
374  * Redistribution and use in source and binary forms, with or without
375  * modification, are permitted provided that the following conditions
376  * are met:
377  * 1. Redistributions of source code must retain the above copyright
378  *    notice, this list of conditions and the following disclaimer.
379  * 2. Redistributions in binary form must reproduce the above copyright
380  *    notice, this list of conditions and the following disclaimer in the
381  *    documentation and/or other materials provided with the distribution.
382  * 3. The name of the author may not be used to endorse or promote products
383  *    derived from this software without specific prior written permission.
384  *
385  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
386  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
387  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
388  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
389  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
390  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
391  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
392  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
393  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
394  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
395  */