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.sesame;
30  
31  import info.aduna.iteration.CloseableIteration;
32  
33  import java.util.ArrayList;
34  import java.util.Collection;
35  import java.util.HashSet;
36  import java.util.Iterator;
37  import java.util.Set;
38  
39  import org.openrdf.elmo.exceptions.ElmoPersistException;
40  import org.openrdf.elmo.exceptions.ElmoIOException;
41  import org.openrdf.elmo.sesame.helpers.PropertyChanger;
42  import org.openrdf.elmo.sesame.roles.SesameEntity;
43  import org.openrdf.model.Literal;
44  import org.openrdf.model.Statement;
45  import org.openrdf.model.Value;
46  import org.openrdf.repository.RepositoryException;
47  import org.openrdf.repository.contextaware.ContextAwareConnection;
48  
49  /**
50   * SesameProperty used for localized properties. Only the best set of literals
51   * are included in the results.
52   * 
53   * @author James Leigh
54   * 
55   * @param <T>
56   */
57  public class LocalizedSesameProperty extends SesameProperty<String> {
58  
59  	public LocalizedSesameProperty(SesameEntity bean, PropertyChanger property) {
60  		super(bean, property);
61  	}
62  
63  	@Override
64  	public void clear() {
65  		ContextAwareConnection conn = getConnection();
66  		try {
67  			boolean autoCommit = conn.isAutoCommit();
68  			if (autoCommit)
69  				conn.setAutoCommit(false);
70  			for (Statement stmt : bestValues()) {
71  				remove(conn, stmt);
72  			}
73  			if (autoCommit)
74  				conn.setAutoCommit(true);
75  		} catch (RepositoryException e) {
76  			throw new ElmoPersistException(e);
77  		}
78  	}
79  
80  	@Override
81  	public String getSingle() {
82  		Iterator<Statement> iter = bestValues().iterator();
83  		if (iter.hasNext())
84  			return createInstance(iter.next());
85  		return null;
86  	}
87  
88  	@Override
89  	public boolean isEmpty() {
90  		Iterator<Statement> iter = bestValues().iterator();
91  		return iter.hasNext();
92  	}
93  
94  	@Override
95  	public Iterator<String> iterator() {
96  		return new Iterator<String>() {
97  			private Iterator<Statement> iter = bestValues().iterator();
98  
99  			private Statement stmt;
100 
101 			public boolean hasNext() {
102 				return iter.hasNext();
103 			}
104 
105 			public String next() {
106 				return createInstance(stmt = iter.next());
107 			}
108 
109 			public void remove() {
110 				try {
111 					ContextAwareConnection conn = getConnection();
112 					LocalizedSesameProperty.this.remove(conn, stmt);
113 				} catch (RepositoryException e) {
114 					throw new ElmoPersistException(e);
115 				}
116 			}
117 
118 		};
119 	}
120 
121 	@Override
122 	public void setAll(Set<String> set) {
123 		if (this == set)
124 			return;
125 		Set<String> c = new HashSet<String>(set);
126 		ContextAwareConnection conn = getConnection();
127 		try {
128 			boolean autoCommit = conn.isAutoCommit();
129 			if (autoCommit)
130 				conn.setAutoCommit(false);
131 			String language = getManager().getLanguage();
132 			CloseableIteration<? extends Statement, RepositoryException> stmts;
133 			stmts = getStatements();
134 			try {
135 				while (stmts.hasNext()) {
136 					Statement stmt = stmts.next();
137 					Literal lit = (Literal) stmt.getObject();
138 					String l = lit.getLanguage();
139 					if (language == l || language != null && language.equals(l)) {
140 						Object next = createInstance(stmt);
141 						if (c.contains(next)) {
142 							c.remove(next);
143 						} else {
144 							remove(conn, stmt);
145 						}
146 					}
147 				}
148 			} finally {
149 				stmts.close();
150 			}
151 			if (c.size() > 0)
152 				addAll(c);
153 			if (autoCommit)
154 				conn.setAutoCommit(true);
155 		} catch (RepositoryException e) {
156 			throw new ElmoPersistException(e);
157 		}
158 	}
159 
160 	@Override
161 	public int size() {
162 		return bestValues().size();
163 	}
164 
165 	@Override
166 	public Object[] toArray() {
167 		return bestValues().toArray();
168 	}
169 
170 	@Override
171 	public <T> T[] toArray(T[] a) {
172 		return bestValues().toArray(a);
173 	}
174 
175 	@Override
176 	protected Value getValue(Object instance) {
177 		return getManager().getLocalizedValue(instance);
178 	}
179 
180 	Collection<Statement> bestValues() {
181 		int score = -1;
182 		Collection<Statement> values = new ArrayList<Statement>();
183 		String language = getManager().getLanguage();
184 		CloseableIteration<? extends Statement, RepositoryException> stmts;
185 		try {
186 			stmts = getStatements();
187 			try {
188 				while (stmts.hasNext()) {
189 					Statement stmt = stmts.next();
190 					score = addBestStatements(stmt, language, score, values);
191 				}
192 			} finally {
193 				stmts.close();
194 			}
195 		} catch (RepositoryException e) {
196 			throw new ElmoIOException(e);
197 		}
198 		return values;
199 	}
200 
201 	private int addBestStatements(Statement stmt, String language, int best,
202 			Collection<Statement> values) {
203 		int score = best;
204 		Literal lit = (Literal) stmt.getObject();
205 		String l = lit.getLanguage();
206 		if (language == l || language != null && language.equals(l)) {
207 			if (score < Integer.MAX_VALUE)
208 				values.clear();
209 			values.add(stmt);
210 			score = Integer.MAX_VALUE;
211 		} else if (l != null && language != null && language.startsWith(l)) {
212 			if (score < l.length())
213 				values.clear();
214 			values.add(stmt);
215 			score = l.length();
216 		} else if (l != null && language != null && score <= 1
217 				&& l.length() > 2 && language.startsWith(l.substring(0, 2))) {
218 			if (score < 1)
219 				values.clear();
220 			values.add(stmt);
221 			score = 1;
222 		} else if (l == null) {
223 			if (score < 0)
224 				values.clear();
225 			values.add(stmt);
226 			score = 0;
227 		} else if (score < 0) {
228 			values.add(stmt);
229 		}
230 		return score;
231 	}
232 
233 }