View Javadoc

1   /*
2    * Copyright (c) 2007, James Leigh All rights reserved.
3    * 
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    * 
7    * - Redistributions of source code must retain the above copyright notice, this
8    *   list of conditions and the following disclaimer.
9    * - Redistributions in binary form must reproduce the above copyright notice,
10   *   this list of conditions and the following disclaimer in the documentation
11   *   and/or other materials provided with the distribution. 
12   * - Neither the name of the openrdf.org nor the names of its contributors may
13   *   be used to endorse or promote products derived from this software without
14   *   specific prior written permission.
15   * 
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26   * POSSIBILITY OF SUCH DAMAGE.
27   * 
28   */
29  package org.openrdf.elmo.dynabean.helpers;
30  
31  import info.aduna.iteration.CloseableIteration;
32  
33  import java.util.ArrayList;
34  import java.util.Collection;
35  import java.util.List;
36  import java.util.concurrent.ConcurrentHashMap;
37  import java.util.concurrent.ConcurrentMap;
38  
39  import org.openrdf.elmo.exceptions.ElmoCompositionException;
40  import org.openrdf.elmo.sesame.SesameManager;
41  import org.openrdf.model.Resource;
42  import org.openrdf.model.Statement;
43  import org.openrdf.model.URI;
44  import org.openrdf.model.Value;
45  import org.openrdf.model.vocabulary.RDF;
46  import org.openrdf.model.vocabulary.RDFS;
47  import org.openrdf.query.QueryEvaluationException;
48  import org.openrdf.repository.RepositoryException;
49  import org.openrdf.repository.contextaware.ContextAwareConnection;
50  
51  /**
52   * creates SesameDynaClasses for the calling SesameDynaBean.
53   * 
54   * @author James Leigh
55   * 
56   */
57  public class DynaClassInfoFactory {
58  
59  	private ConcurrentMap<Collection<URI>, DynaClassInfo> dynaClasses = new ConcurrentHashMap<Collection<URI>, DynaClassInfo>();
60  
61  	public DynaClassInfo findDyanClass(SesameManager manager, Resource resource) {
62  		try {
63  			Collection<URI> rdfTypes = new ArrayList<URI>();
64  			ContextAwareConnection conn = manager.getConnection();
65  			CloseableIteration<? extends Statement, RepositoryException> iter;
66  			iter = conn.getStatements(resource, RDF.TYPE, null);
67  			try {
68  				while (iter.hasNext()) {
69  					Value object = iter.next().getObject();
70  					if (object instanceof URI)
71  						rdfTypes.add((URI) object);
72  				}
73  			} finally {
74  				iter.close();
75  			}
76  			if (dynaClasses.containsKey(rdfTypes))
77  				return dynaClasses.get(rdfTypes);
78  			DynaClassInfo c = buildDynaClass(manager, rdfTypes);
79  			DynaClassInfo o = dynaClasses.putIfAbsent(rdfTypes, c);
80  			if (o != null) {
81  				c = o;
82  			}
83  			return c;
84  		} catch (RepositoryException e) {
85  			throw new ElmoCompositionException(e);
86  		} catch (QueryEvaluationException e) {
87  			throw new ElmoCompositionException(e);
88  		}
89  	}
90  
91  	public synchronized DynaClassInfo buildDynaClass(SesameManager manager,
92  			Collection<URI> rdfTypes) throws RepositoryException,
93  			QueryEvaluationException {
94  		if (dynaClasses.containsKey(rdfTypes))
95  			return dynaClasses.get(rdfTypes);
96  		ContextAwareConnection conn = manager.getConnection();
97  		RdfsClassInterpreter interpreter = new RdfsClassInterpreter(conn);
98  		List<URI> list = new ArrayList<URI>(rdfTypes.size() + 1);
99  		list.addAll(rdfTypes);
100 		if (!rdfTypes.contains(RDFS.RESOURCE))
101 			list.add(RDFS.RESOURCE);
102 		List<URI> filtered = filterOutSuperclasses(conn, list);
103 		DynaClassInfo c = new DynaClassInfo(filtered);
104 		interpreter.interpetRdfClass(list, c);
105 		dynaClasses.put(rdfTypes, c);
106 		return c;
107 	}
108 
109 	private List<URI> filterOutSuperclasses(ContextAwareConnection conn,
110 			List<URI> types) throws RepositoryException {
111 		if (types.size() < 2)
112 			return types;
113 		ArrayList<URI> list = new ArrayList<URI>(types.size());
114 		for (int i = 0, n = types.size(); i < n; i++) {
115 			URI c = types.get(i);
116 			boolean isSubClass = false;
117 			for (int j = 0, m = types.size(); j < m; j++) {
118 				if (i == j)
119 					continue;
120 				URI d = types.get(j);
121 				if (c.equals(d)) {
122 					isSubClass = true;
123 					break;
124 				}
125 				boolean subclass = conn.hasStatement(d, RDFS.SUBCLASSOF, c,
126 						true);
127 				if (subclass) {
128 					isSubClass = true;
129 					break;
130 				}
131 			}
132 			if (!isSubClass)
133 				list.add(c);
134 		}
135 		return list;
136 	}
137 
138 }