View Javadoc

1   /*
2    * Copyright (c) 2007, Peter Mika 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.smusher;
30  
31  /** Utility methods for Elmo
32   * @author Peter Mika (pmika@cs.vu.nl)
33   */
34  
35  import info.aduna.collections.iterators.Iterators;
36  
37  import java.io.IOException;
38  import java.io.UnsupportedEncodingException;
39  import java.net.MalformedURLException;
40  import java.net.URL;
41  import java.security.MessageDigest;
42  import java.security.NoSuchAlgorithmException;
43  import java.util.Enumeration;
44  import java.util.Hashtable;
45  import java.util.List;
46  
47  import javax.servlet.ServletConfig;
48  import javax.servlet.ServletContext;
49  import javax.servlet.ServletException;
50  import javax.servlet.http.HttpServletRequest;
51  
52  import org.openrdf.OpenRDFException;
53  import org.openrdf.elmo.ElmoManager;
54  import org.openrdf.elmo.ElmoManagerFactory;
55  import org.openrdf.elmo.ElmoModule;
56  import org.openrdf.elmo.ElmoQuery;
57  import org.openrdf.elmo.sesame.SesameManager;
58  import org.openrdf.elmo.sesame.SesameManagerFactory;
59  import org.openrdf.model.Literal;
60  import org.openrdf.model.Statement;
61  import org.openrdf.model.URI;
62  import org.openrdf.model.impl.LiteralImpl;
63  import org.openrdf.repository.Repository;
64  import org.openrdf.repository.RepositoryConnection;
65  import org.openrdf.repository.RepositoryException;
66  import org.openrdf.repository.http.HTTPRepository;
67  import org.slf4j.Logger;
68  import org.slf4j.LoggerFactory;
69  
70  public class Util {
71  
72  	//Similarity threshold for matching names
73  	public final static double SIMILARITY_THRESHOLD = 0.85;
74  
75  	private final static int NGRAM_SIZE = 2;
76  
77  	  
78  	//servlet parameter names used for init and config parameters
79  	public final static String SERVLET_SERVER_PARAMETER = "server";
80  
81  	public final static String SERVLET_REPOSITORY_PARAMETER = "repository";
82  
83  	public final static String SERVLET_USERNAME_PARAMETER = "username";
84  
85  	public final static String SERVLET_PASSWORD_PARAMETER = "password";
86  	
87  	public final static String CONTEXT_SERVER_PARAMETER = SERVLET_SERVER_PARAMETER;
88  
89  	public final static String CONTEXT_REPOSITORY_PARAMETER = SERVLET_REPOSITORY_PARAMETER;
90  		
91  	public final static String CONTEXT_USERNAME_PARAMETER = SERVLET_USERNAME_PARAMETER;
92  
93  	public final static String CONTEXT_PASSWORD_PARAMETER = SERVLET_PASSWORD_PARAMETER;
94  
95  	//request attribute names
96  	public final static String REQUEST_REPOSITORY_ATTRIBUTE = "sesame";
97  
98  	protected static Logger _logger = LoggerFactory.getLogger(Util.class);
99  
100 
101 	
102 	private static Repository getLocalRepository(String name) throws RepositoryException {
103 		/*
104 		RepositoryManager manager = RepositoryManager.getDefaultInstance();
105 		
106 		Repository repository = manager.getRepository(name);
107 		repository.initialize();
108 		
109 		return repository;
110 		*/
111 		throw new RuntimeException("Not implemented");
112 	}
113 	
114 	private static Repository getRemoteRepository(String sesameServer, String repositoryID) throws RepositoryException {
115 		Repository repository = new HTTPRepository(sesameServer, repositoryID);
116 		repository.initialize();
117 		
118 		return repository;
119 	}
120 	
121 	public static SesameManager initManager(Repository repository) {
122 		ElmoManagerFactory factory = new SesameManagerFactory(new ElmoModule(), repository);
123 		ElmoManager manager = factory.createElmoManager();
124 
125 		return (SesameManager) manager;
126 	}
127 	
128 	/** Initialize a remote Elmo repository using the location and name
129 	 * 
130 	 * @param repositoryLocation String containing a URL
131 	 * @param repositoryName Repository name
132 	 * @return Repository
133 	 * @throws Exception if parameter is missing, invalid or initilization failed
134 	 * @see org.openrdf.elmo.repository.ElmoRepository#getRepository(URL, String)
135 	 */
136 	public static Repository initRepository(String repositoryLocation,
137 			String repositoryName) throws Exception {
138 		return initRepository(repositoryLocation, repositoryName, null, null);
139 	}
140 
141 	
142 	/**
143 	 * Initialize a remote Elmo repository using (optional) username and password.
144 	 * Performs some sanity checks on the repository location and name.
145 	 *  
146 	 * @param repositoryLocation
147 	 *            URL of the server
148 	 * @param repositoryName
149 	 *            Repository name
150 	 * @param username
151 	 *            Optional username
152 	 * @param password
153 	 *            Optional password
154 	 * @return Repository
155 	 * @throws Exception
156 	 *             if parameter is missing, invalid or initilization failed
157 	 */
158 			
159 	public static Repository initRepository(String repositoryLocation,
160 			String repositoryName, String username, String password)
161 			throws Exception {
162 		Repository repository = null;
163 		
164 		//Check parameters
165 		if ((repositoryLocation == null || repositoryLocation.equals("")) &&
166 			repositoryName != null && !repositoryName.equals("")) {
167 			//try getting the repository from the Sesame server in the same JVM
168 		
169 			
170 			repository = getLocalRepository(repositoryName);
171 			
172 		} else {
173 			
174 			try {
175 				URL repositoryURL = new URL(repositoryLocation);
176 			} catch (MalformedURLException mue) {
177 				throw new Exception("Repository location contains a malformed URL");
178 			}
179 			if (repositoryName == null || repositoryName.equals("")) {
180 				throw new Exception("Repository name missing");
181 			}
182 	
183 			repository = getRemoteRepository(repositoryLocation, repositoryName);
184 			
185 		}
186 	
187 		return repository;
188 	}
189 	
190 	
191 
192 	/**
193 	 * Initialize an Elmo repository from servlet request. First try to find a
194 	 * SesameRepository as a request attribute , if fails try to initialize one
195 	 * using request parameter. The attribute and init parameter names to
196 	 * specified are defined as constants in this class.
197 	 * 
198 	 * @param request
199 	 *            Request with parameters
200 	 * @return Repository
201 	 * @throws ServletException
202 	 *             if parameters are missing or repository failed to initialize
203 	 * @see #REQUEST_REPOSITORY_ATTRIBUTE
204 	 * @see #SERVLET_SERVER_PARAMETER
205 	 * @see #SERVLET_REPOSITORY_PARAMETER
206 	 * @see #SERVLET_USERNAME_PARAMETER
207 	 * @see #SERVLET_USERNAME_PARAMETER
208 	 */
209 	public static Repository initRepository(HttpServletRequest request)
210 			throws ServletException {
211 		String repositoryLocation = null;
212 		String repositoryName = null;
213 		String userName = null;
214 		String password = null;
215 		
216 		Repository repository = null;
217 		//Try first to find an object in the request
218 		if (request.getAttribute(REQUEST_REPOSITORY_ATTRIBUTE) != null) {
219 			repository = (Repository) request
220 					.getAttribute(REQUEST_REPOSITORY_ATTRIBUTE);
221 		} else {
222 			//SERVER and REPOSITORY
223 			repositoryLocation = request.getParameter(SERVLET_SERVER_PARAMETER);
224 			repositoryName = request.getParameter(SERVLET_REPOSITORY_PARAMETER);
225 
226 			if (request.getParameter(SERVLET_USERNAME_PARAMETER) != null
227 					&& request.getParameter(SERVLET_PASSWORD_PARAMETER) != null) {
228 				//USERNAME and PASSWORD
229 				userName = request.getParameter(SERVLET_USERNAME_PARAMETER);
230 				password = request.getParameter(SERVLET_PASSWORD_PARAMETER);
231 			}
232 
233 			try {
234 				repository = Util.initRepository(repositoryLocation,
235 						repositoryName, userName, password);
236 			} catch (Exception e) {
237 				throw new ServletException("Repository failed to initialize", e);
238 			}
239 		}
240 		return repository;
241 	}
242 	
243 	/**
244 	 * Initialize an Elmo repository from servlet initialization parameters and 
245 	 * if that fails from the context initialization parameters.
246 	 * 
247 	 * The init parameter names to specified are defined as constants in this
248 	 * class.
249 	 * 
250 	 * @param config
251 	 *            ServletConfig instance
252 	 * @return Repository
253 	 * @throws ServletException
254 	 *             if parameters are missing or repository failed to initialize
255 	 * @see #SERVLET_SERVER_PARAMETER
256 	 * @see #SERVLET_REPOSITORY_PARAMETER
257 	 * @see #SERVLET_USERNAME_PARAMETER
258 	 * @see #SERVLET_PASSWORD_PARAMETER
259 	 * @see #CONTEXT_SERVER_PARAMETER
260 	 * @see #CONTEXT_REPOSITORY_PARAMETER
261 	 * @see #CONTEXT_USERNAME_PARAMETER
262 	 * @see #CONTEXT_PASSWORD_PARAMETER
263 
264 	 */
265 	public static Repository initRepository(ServletConfig config)
266 			throws ServletException {
267 		String repositoryLocation = null;
268 		String repositoryName = null;
269 		String userName = null;
270 		String password = null;
271 		
272 		Repository repository = null;
273 			
274 		repositoryLocation = config.getInitParameter(SERVLET_SERVER_PARAMETER);
275 		repositoryName = config.getInitParameter(SERVLET_REPOSITORY_PARAMETER);
276 		
277 		if (config.getInitParameter(SERVLET_USERNAME_PARAMETER) != null
278 				&& config.getInitParameter(SERVLET_PASSWORD_PARAMETER) != null) {
279 			//USERNAME and PASSWORD
280 			userName = config.getInitParameter(SERVLET_USERNAME_PARAMETER);
281 			password = config.getInitParameter(SERVLET_PASSWORD_PARAMETER);
282 		}
283 
284 		try {
285 			repository = Util.initRepository(repositoryLocation, repositoryName,
286 					userName, password);
287 			return repository;
288 		} catch (Exception e) {
289 			//ignore
290 		}
291 		
292 		//try context parameters
293 		ServletContext context = config.getServletContext();
294 		repositoryLocation = context.getInitParameter(CONTEXT_SERVER_PARAMETER);
295 		repositoryName = context.getInitParameter(CONTEXT_REPOSITORY_PARAMETER);
296 		
297 		if (context.getInitParameter(CONTEXT_USERNAME_PARAMETER) != null
298 				&& context.getInitParameter(CONTEXT_PASSWORD_PARAMETER) != null) {
299 			//USERNAME and PASSWORD
300 			userName = context.getInitParameter(CONTEXT_USERNAME_PARAMETER);
301 			password = context.getInitParameter(CONTEXT_PASSWORD_PARAMETER);
302 		} else {
303 			userName = null;
304 			password = null;
305 		}
306 
307 		try {
308 			repository = Util.initRepository(repositoryLocation, repositoryName,
309 					userName, password);
310 		} catch (Exception e) {
311 			throw new ServletException("Repository failed to initialize", e);
312 		}
313 		
314 		return repository;
315 	}
316 		
317 	
318 
319 	/**
320 	 * Initialize an Elmo repository from either servlet request parameters or
321 	 * servlet initialization parameters. First try to find a ElmoRepository
322 	 * object in the request. If not present, try to initialize one based on
323 	 * request parameters. If this also fails, try to use servlet init
324 	 * parameters and lastly the context initialization paratemers. 
325 	 * The attribute, request and init parameter names to specified
326 	 * are defined as constants in this class.
327 	 * 
328 	 * @param servlet
329 	 *            Servlet instance
330 	 * @param request
331 	 *            Request with parameters
332 	 * @return Repository
333 	 * @throws ServletException
334 	 *             if parameters are missing or repository failed to initialize
335 	 * @see #REQUEST_REPOSITORY_ATTRIBUTE
336 	 * @see #SERVLET_SERVER_PARAMETER
337 	 * @see #SERVLET_REPOSITORY_PARAMETER
338 	 * @see #SERVLET_USERNAME_PARAMETER
339 	 * @see #SERVLET_USERNAME_PARAMETER
340 	 * @see #CONTEXT_SERVER_PARAMETER
341 	 * @see #CONTEXT_REPOSITORY_PARAMETER
342 	 * @see #CONTEXT_USERNAME_PARAMETER
343 	 * @see #CONTEXT_USERNAME_PARAMETER
344 	 */
345 	public static Repository initRepository(ServletConfig config,
346 			HttpServletRequest request) throws ServletException {
347 		Repository repository = null;
348 		//first try to initialize a repository from the request parameters
349 		try {
350 			repository = initRepository(request);
351 
352 		} catch (ServletException se) {
353 			//ignore
354 		}
355 		//if fails, try the initialization parameters
356 		if (repository == null) {
357 			repository = initRepository(config);
358 		}
359 		return repository;
360 	}
361 
362 	private static class Gram {
363 		String gram;
364 
365 		int occurences;
366 
367 		String str;
368 
369 		public Gram(String inGram, String inString) {
370 			gram = inGram;
371 			str = inString;
372 			occurences = 0;
373 			int ng = gram.length();
374 			int len = str.length();
375 			for (int i = 0; i <= (len - ng); i++) {
376 				String gr = str.substring(i, i + ng);
377 				if (gram.equalsIgnoreCase(gr)) {
378 					occurences++;
379 				}
380 			}
381 		}
382 	}
383 
384 	//ngram size shouldn't be less than 2 and more than 9
385 	public static double compare(String str1, String str2, int ng) {
386 		if (ng < 2) {
387 			ng = 2;
388 		}
389 		if (ng > 9) {
390 			ng = 9;
391 		}
392 		char blank = ' ';
393 		char underline = '_';
394 		str1 = str1.replace(blank, underline);
395 		str2 = str2.replace(blank, underline);
396 
397 		Hashtable<String, Gram> gramList1 = new Hashtable<String, Gram>();
398 		int len = str1.length();
399 		for (int i = 0; i <= (len - ng); i++) {
400 			String gr = str1.substring(i, i + ng);
401 			Gram gram = new Gram(gr, str1);
402 			if (gram.occurences > 0) {
403 				gramList1.put(gram.gram, gram);
404 			}
405 		}
406 		Hashtable<String, Gram> gramList2 = new Hashtable<String, Gram>();
407 		len = str2.length();
408 		for (int i = 0; i <= (len - ng); i++) {
409 			String gr = str2.substring(i, i + ng);
410 			Gram gram = new Gram(gr, str2);
411 			if (gram.occurences > 0) {
412 				gramList2.put(gram.gram, gram);
413 			}
414 		}
415 		double difference = 0;
416 		double sum = 0;
417 		Hashtable<String, Gram> diffGrams = new Hashtable<String, Gram>();
418 
419 		Enumeration keys1 = gramList1.keys();
420 		while (keys1.hasMoreElements()) {
421 			String key = (String) keys1.nextElement();
422 			Gram g = (Gram) gramList1.get(key);
423 			double plus = (g.occurences);
424 			double squarePlus = Math.pow(plus, 2);
425 			sum = sum + squarePlus;
426 			if (gramList2.containsKey(key)) {
427 				Gram gr2 = (Gram) gramList2.get(key);
428 				double minus = (g.occurences - gr2.occurences);
429 				double square = Math.pow(minus, 2);
430 				difference = difference + square;
431 			} else {
432 				double square = Math.pow(g.occurences, 2);
433 				difference = difference + square;
434 			}
435 		}
436 		Enumeration keys2 = gramList2.keys();
437 		while (keys2.hasMoreElements()) {
438 			String key = (String) keys2.nextElement();
439 			Gram gr2 = (Gram) gramList2.get(key);
440 			if (gramList1.containsKey(key)) {
441 			} else {
442 				diffGrams.put(key, gr2);
443 			}
444 		}
445 		Enumeration diffKeys = diffGrams.keys();
446 		while (diffKeys.hasMoreElements()) {
447 			String key = (String) diffKeys.nextElement();
448 			Gram diffGram = (Gram) diffGrams.get(key);
449 			double square = Math.pow(diffGram.occurences, 2);
450 			difference = difference + square;
451 			double squarePlus = Math.pow(diffGram.occurences, 2);
452 			sum = sum + squarePlus;
453 		}
454 
455 		int totalLength = str1.length() - ng + 1 + diffGrams.size();
456 		double threshold = 2.486 + 0.025 * totalLength;
457 		difference = Math.sqrt(difference);
458 		//sum is not used any more
459 		//sum = Math.sqrt(sum);
460 
461 		//Alternatively:
462 		double similarity = 0;
463 		if (difference < threshold) {
464 			similarity = 0.8 + ((threshold - difference) / (5 * threshold));
465 		} else if (difference > threshold) {
466 			similarity = 0.8 - (((difference - threshold) * 4) / ((1 + difference - threshold) * 5));
467 		} else {
468 			similarity = 0.8;
469 		}
470 
471 		return similarity;
472 	}
473 	
474 	
475 	
476 	/** Invert names of the from "van Harmelen, Frank", i.e. with comma. 
477 	 * 
478 	 * @param name Name
479 	 * @return Name in its regular form or unchanged if no comma is found
480 	 */
481 	public static String invertName(String name) {
482 		int delim = name.indexOf(',');
483         if (delim != -1) {
484             return name.substring(delim + 1, name.length()).trim() + ' ' +
485 			       name.substring(0, delim).trim();
486         } else {
487             return name;
488         }
489 	}
490 	
491 
492 	/** Extract the first name from a full name
493 	 * 
494 	 * @param name Name
495 	 * @return First name
496 	 */
497 	public static String getFirstName(String name) {
498 		//if there is a comma then first name is last
499 		if (name.indexOf(',') != -1) {
500 			name = invertName(name);
501 		} 
502 		int delim = name.indexOf(" ");
503 		if (delim < 0) {
504 			//no space -> name is a firstname
505 			delim = name.length();
506 		}
507 		return name.substring(0, delim);
508 	}
509 
510 	/** Extract the last name from a full name
511 	 * 
512 	 * @param name Name
513 	 * @return Last name
514 	 */
515 	public static String getLastName(String name) {
516 		//if there is a comma then last name is first
517 		if (name.indexOf(',') != -1) {
518 			name = invertName(name);
519 		} 
520 		int delim = name.lastIndexOf(" ");
521 		if (delim < 0) {
522 			//no space -> name is a firstname
523 			return "";
524 		} else {
525 			return name.substring(delim + 1, name.length());
526 		}
527 	}
528 
529 	/** Determine if two names are the same using N-Gram matching.
530 	 * The similarity threshold is determined by {@link #SIMILARITY_THRESHOLD}
531 	 * 
532 	 * @param name1 First name
533 	 * @param name2 Second name
534 	 * @return True, if the names are the same (similar enough)
535 	 */
536 	public static boolean matchNames(String name1, String name2) {
537 		boolean result = true;
538 		//Parse the names
539 		String first1 = getFirstName(name1.trim());
540 		String last1 = getLastName(name1.trim());
541 		String first2 = getFirstName(name2.trim());
542 		String last2 = getLastName(name2.trim());
543 
544 		//If we only have firstnames, we cannot match
545 		if (last1.length() < 2 || last2.length() < 2) {
546 			return false;
547 		}
548 
549 		//The last names must match exactly
550 		if (!last1.equalsIgnoreCase(last2)) {
551 			return false;
552 		}
553 		
554 		//Check if one of the first names contains an initial
555 		//If yes, compare only the initial characters
556 		if (first1.indexOf(".") != -1 || first2.indexOf(".") != -1) {
557 			if (!(first1.charAt(0) == first2.charAt(0))) {
558 				return false;
559 			}
560 		} else {
561 			//The first names must be similar enough
562 			if (//check if the names are long enough
563 			//(first1.length() > STRINGLENGTH_THRESHOLD) &&
564 			//(first2.length() > STRINGLENGTH_THRESHOLD) &&
565 			compare(first1, first2, NGRAM_SIZE) < SIMILARITY_THRESHOLD) {
566 				return false;
567 			}
568 		}
569 
570 		return result;
571 	}
572 			
573 	/** Add a statement to a repository
574 	 * 
575 	 * @param rep
576 	 * @param stmt
577 	 * @throws OpenRDFException
578 	 * @throws IOException
579 	 */
580 	public static void addStatememt(Repository rep, Statement stmt)
581 	throws OpenRDFException, IOException {
582 		RepositoryConnection con = null;
583 		
584 		try {
585 			con = rep.getConnection();
586 			
587 			con.add(stmt);
588 		} 
589 		finally {
590 			if (con != null)
591 				con.close();
592 			
593 
594 		}
595 	}
596 
597   
598 	/** Get all instances of type T from a given repository
599 	 * 
600 	 * @param <T>
601 	 * @param rep
602 	 * @param cl
603 	 * @return
604 	 */
605 	public static <T extends org.openrdf.concepts.rdfs.Resource> List<T> getAllInstances(ElmoManager manager, Class<T> cl) {
606 		//SesameManagerFactory factory = new SesameManagerFactory(rep);
607 		//SesameManager manager = factory.createElmoManager();
608 		Iterable<T> query = manager.findAll(cl);
609 		return Iterators.asList(query.iterator());
610 	}
611 
612 	
613 
614 	/** Generate a SHA1 digest of the string passed in and
615 	 *  encode using hex encoding.
616 	 * 
617 	 * @param str String to be encoded
618 	 * @return Digest
619 	 */
620 	public final static String createSHA1(String str) 
621 	throws UnsupportedEncodingException, NoSuchAlgorithmException {
622 	    String result = "";
623 	    byte[] theTextToDigestAsBytes = str.getBytes( "8859_1" /* encoding */ );
624 	    MessageDigest md = MessageDigest.getInstance( "SHA" );
625 	    md.update( theTextToDigestAsBytes );
626 	    byte[] digest = md.digest();
627 	    //Write out a formatted string
628 	    for (int i=0; i<digest.length; i++) {
629 	        String hex = Integer.toHexString(digest[i]);
630 	        if (hex.length() == 1) hex = "0" + hex;
631 	        result += hex.substring(hex.length()-2);
632 	    }
633 	    return result.toUpperCase();
634 	}
635 	
636 	/** Generate a SHA1 summary of an email address String
637 	 *  (e.g. "pmika@cs.vu.nl")
638 	 *  according the FOAF specification of the mbox_sha1sum property.
639 	 * 
640 	 * @param str E-mail address
641 	 * @return Mailbox checksum
642 	 */
643 	public final static Literal createSha1Sum(String email) 
644 	throws UnsupportedEncodingException, NoSuchAlgorithmException  {
645 	    return new LiteralImpl(createSHA1("mailto:" + email));
646 	}
647 	
648 	/** Generate a SHA1 summary of an email address URI
649 	 *  (e.g. <mailto:pmika@cs.vu.nl>)
650 	 *  according the FOAF specification of the mbox_sha1sum property.
651 	 * 
652 	 * @param str
653 	 * @return Mailbox checksum
654 	 */
655 	public final static Literal createSha1Sum(URI email) 
656 	throws UnsupportedEncodingException, NoSuchAlgorithmException  {
657 	    return new LiteralImpl(createSHA1(email.toString()));
658 	}
659 
660 }