PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/iks-ri/branches/alpha/rick/generic/core/src/main/java/eu/iksproject/rick/core/utils/ModelUtils.java

http://iks-project.googlecode.com/
Java | 289 lines | 184 code | 12 blank | 93 comment | 47 complexity | f21857d3c4bd93c3ca79c67586fb84de MD5 | raw file
Possible License(s): CC-BY-3.0
  1. package eu.iksproject.rick.core.utils;
  2. import java.net.URI;
  3. import java.net.URL;
  4. import java.util.ArrayList;
  5. import java.util.Collection;
  6. import java.util.Collections;
  7. import java.util.Enumeration;
  8. import java.util.HashMap;
  9. import java.util.Iterator;
  10. import java.util.Map;
  11. import java.util.Random;
  12. import java.util.UUID;
  13. import javax.xml.namespace.QName;
  14. import org.slf4j.Logger;
  15. import org.slf4j.LoggerFactory;
  16. import eu.iksproject.rick.core.model.DefaultEntityMappingImpl;
  17. import eu.iksproject.rick.core.model.DefaultSignImpl;
  18. import eu.iksproject.rick.core.model.DefaultSymbolImpl;
  19. import eu.iksproject.rick.servicesapi.defaults.NamespaceEnum;
  20. import eu.iksproject.rick.servicesapi.model.Reference;
  21. import eu.iksproject.rick.servicesapi.model.Representation;
  22. import eu.iksproject.rick.servicesapi.model.Sign;
  23. import eu.iksproject.rick.servicesapi.model.Text;
  24. import eu.iksproject.rick.servicesapi.model.ValueFactory;
  25. import eu.iksproject.rick.servicesapi.model.Sign.SignTypeEnum;
  26. import eu.iksproject.rick.servicesapi.model.rdf.RdfResourceEnum;
  27. /**
  28. * Utilities useful for implementations of the Rick Model
  29. * @author Rupert Westenthaler
  30. *
  31. */
  32. public final class ModelUtils {
  33. private static final Logger log = LoggerFactory.getLogger(ModelUtils.class);
  34. /**
  35. * Holds the uri->RepresentationTypeEnum mappings
  36. */
  37. public static final Map<String,SignTypeEnum> REPRESENTATION_TYPE_MAPPING;
  38. static {
  39. Map<String,SignTypeEnum> repTypeMapping = new HashMap<String, SignTypeEnum>();
  40. for(SignTypeEnum type : SignTypeEnum.values()){
  41. repTypeMapping.put(type.getUri(), type);
  42. }
  43. REPRESENTATION_TYPE_MAPPING = Collections.unmodifiableMap(repTypeMapping);
  44. }
  45. /**
  46. * Getter for the {@link SignTypeEnum} based on the reference
  47. * @param referece The reference as defined by {@link SignTypeEnum#getUri()}
  48. * @return the type or <code>null</code> if no mapping is present for the parsed
  49. * reference.
  50. */
  51. public static SignTypeEnum getSignType(Reference reference){
  52. return reference == null?null:getSignType(reference.getReference());
  53. }
  54. /**
  55. * Getter for the {@link SignTypeEnum} based on the uri
  56. * @param uri The uri as defined by {@link SignTypeEnum#getUri()}
  57. * @return the type or <code>null</code> if no mapping is present for the parsed
  58. * uri.
  59. */
  60. public static SignTypeEnum getSignType(String uri){
  61. return REPRESENTATION_TYPE_MAPPING.get(uri);
  62. }
  63. /**
  64. * Random UUID generator with re-seedable RNG for the tests.
  65. *
  66. * @return a new Random UUID
  67. */
  68. protected static Random rng = new Random();
  69. /**
  70. * Do not allow instances of this class
  71. */
  72. private ModelUtils(){}
  73. /**
  74. * TODO: Maybe we need a better way to generate unique IDs
  75. * @return
  76. */
  77. public static UUID randomUUID() {
  78. return new UUID(rng.nextLong(), rng.nextLong());
  79. }
  80. public static void setSeed(long seed) {
  81. rng.setSeed(seed);
  82. }
  83. /**
  84. * Processes a value parsed as object to the representation.
  85. * This processing includes:
  86. * <ul>
  87. * <li> Converting URIs and URLs to {@link Reference}
  88. * <li> Converting String[] with at least a single entry where the first
  89. * entry is not null to {@link Text} (the second entry is used as language.
  90. * Further entries are ignored.
  91. * <li> Recursive calling of this Method if a {@link Iterable} (any Array or
  92. * {@link Collection}), {@link Iterator} or {@link Enumeration} is parsed.
  93. * <li> All other Objects are added to the result list
  94. * </ul>
  95. * @param value the value to parse
  96. * @param results the collections the results of the parsing are added to.
  97. */
  98. public static void checkValues(ValueFactory valueFactory, Object value,Collection<Object> results){
  99. if(value instanceof Iterable<?>){
  100. for(Object current : (Iterable<?>)value){
  101. checkValues(valueFactory,current,results);
  102. }
  103. } else if(value instanceof Iterator<?>){
  104. while(((Iterator<?>)value).hasNext()){
  105. checkValues(valueFactory,((Iterator<?>)value).next(),results);
  106. }
  107. } else if(value instanceof Enumeration<?>){
  108. while(((Enumeration<?>)value).hasMoreElements()){
  109. checkValues(valueFactory,((Enumeration<?>)value).nextElement(),results);
  110. }
  111. } else if(value instanceof URI || value instanceof URL){
  112. results.add(valueFactory.createReference(value.toString()));
  113. } else if(value instanceof String[]){
  114. if(((String[])value).length>0 && ((String[])value)[0] != null){
  115. results.add(valueFactory.createText(((String[])value)[0],
  116. ((String[])value).length>1?((String[])value)[1]:null));
  117. } else {
  118. log.warn("String[] "+value+" is not a valied natural language array! -> ignore value");
  119. }
  120. } else {
  121. results.add(value);
  122. }
  123. }
  124. public static String getRepresentationInfo(Representation rep) {
  125. StringBuilder info = new StringBuilder();
  126. info.append("Representation id=");
  127. info.append(rep.getId());
  128. info.append(" | impl=");
  129. info.append(rep.getClass());
  130. info.append('\n');
  131. for(Iterator<String> fields = rep.getFieldNames();fields.hasNext();){
  132. String field = fields.next();
  133. info.append(" o ");
  134. info.append(field);
  135. info.append(':');
  136. Collection<Object> values = new ArrayList<Object>();
  137. for(Iterator<Object> valueIt = rep.get(field);valueIt.hasNext();){
  138. values.add(valueIt.next());
  139. }
  140. info.append(values);
  141. info.append('\n');
  142. }
  143. return info.toString();
  144. }
  145. public static <T> Collection<T> asCollection(Iterator<T> it){
  146. Collection<T> c = new ArrayList<T>();
  147. while(it.hasNext()){
  148. c.add(it.next());
  149. }
  150. return c;
  151. };
  152. /**
  153. * Splits up a URI in local name and namespace based on the following rules
  154. * <ul>
  155. * <li> If URI starts with "urn:" and last index of ':' == 3 than the there
  156. * is no namespace and the whole URI is a local name
  157. * <li> if the uri starts with "urn:" and the last index of ':' ia > 3, than
  158. * the last index ':' is used.
  159. * <li> split by the last index of '#' if index >= 0
  160. * <li> split by the last index of '/' if index >= 0
  161. * <li> return after the first split
  162. * <li> return the whole URI as local name if no split was performed.
  163. * </ul>
  164. * @param uri The uri
  165. * @return A array with two fields. In the first the namespace is stored (
  166. * might be <code>null</code>. In the second the local name is stored.
  167. */
  168. public static String[] getNamespaceLocalName(String uri){
  169. String[] parts = new String[2];
  170. if(uri.startsWith("urn:")){
  171. if(uri.lastIndexOf(':')>3){
  172. parts[1] = uri.substring(uri.lastIndexOf(":")+1);
  173. parts[0] = uri.substring(0, uri.lastIndexOf(":")+1);
  174. } else {
  175. parts[1] = uri;
  176. parts[0] = null;
  177. }
  178. } else if(uri.lastIndexOf("#")>=0){
  179. parts[1] = uri.substring(uri.lastIndexOf("#")+1);
  180. parts[0] = uri.substring(0, uri.lastIndexOf("#")+1);
  181. } else if(uri.lastIndexOf("/")>=0){
  182. parts[1] = uri.substring(uri.lastIndexOf("/")+1);
  183. parts[0] = uri.substring(0, uri.lastIndexOf("/")+1);
  184. } else {
  185. parts[0] = null;
  186. parts[1] = uri;
  187. }
  188. return parts;
  189. }
  190. /**
  191. * This Method uses {@link #getNamespaceLocalName(String)} to split up
  192. * namespace and local name. It uses also the Data in the
  193. * {@link NamespaceEnum} to retrieve prefixes for Namespaces.
  194. * @param uri the URI
  195. * @return the QName
  196. */
  197. public static QName getQName(String uri){
  198. String[] nsln = getNamespaceLocalName(uri);
  199. if(nsln[0] != null){
  200. NamespaceEnum entry = NamespaceEnum.forNamespace(nsln[0]);
  201. if(entry != null){
  202. return new QName(nsln[0], nsln[1],entry.getPrefix());
  203. } else {
  204. return new QName(nsln[0], nsln[1]);
  205. }
  206. } else {
  207. return new QName(nsln[1]);
  208. }
  209. }
  210. /**
  211. * Getter for the SignType for a Representation. If the Representation does
  212. * not define a value part of the {@link SignTypeEnum} for the field
  213. * {@link RdfResourceEnum#signType} ({@value RdfResourceEnum#signType}), that
  214. * the default sign type {@link Sign#DEFAULT_SIGN_TYPE} is returned.
  215. * @param representation The representation
  216. * @return the sign type
  217. * @throws IllegalArgumentException if <code>null</code> is parsed as representation!
  218. */
  219. public static SignTypeEnum getSignType(Representation representation) throws IllegalArgumentException {
  220. if(representation == null){
  221. throw new IllegalArgumentException("Parameter represetnation MUST NOT be NULL!");
  222. }
  223. Reference ref = representation.getFirstReference(RdfResourceEnum.signType.getUri());
  224. if(ref == null){
  225. return Sign.DEFAULT_SIGN_TYPE;
  226. } else {
  227. SignTypeEnum type = ModelUtils.getSignType(ref.getReference());
  228. if(type == null){
  229. log.warn("Sign "+representation.getId()+" is set to an unknown SignType "+ref.getReference()+"! -> return default type (value is not reseted)");
  230. return Sign.DEFAULT_SIGN_TYPE;
  231. } else {
  232. return type;
  233. }
  234. }
  235. }
  236. /**
  237. * Creates a Sign for the parsed Representation and the signSite id
  238. * @param rep the Represetnation
  239. * @param signSite the id of the site for the sign
  240. * @return the sign
  241. * @throws IllegalArgumentException if any of the two parameter is <code>null</code>.
  242. */
  243. public static Sign createSign(Representation rep,String signSite) throws IllegalArgumentException {
  244. if(rep == null){
  245. throw new IllegalArgumentException("The parsed Representation MUST NOT be NULL!");
  246. }
  247. if(signSite == null){
  248. throw new IllegalArgumentException("The parsed ID of the SignSite MUST NOT be NULL!");
  249. }
  250. rep.setReference(Sign.SIGN_SITE, signSite);
  251. SignTypeEnum signType = ModelUtils.getSignType(rep);
  252. //instantiate the correct Sign Implementation
  253. Sign sign;
  254. /*
  255. * TODO: change this part to separate the implementation of the
  256. * ReferencedSite with the instantiation of Sign Type Implementations
  257. * Maybe introduce an SignFactory or add such Methods to the
  258. * existing ValueFactory
  259. */
  260. switch (signType) {
  261. case Symbol:
  262. sign = new DefaultSymbolImpl(signSite,rep);
  263. break;
  264. case EntityMapping:
  265. sign = new DefaultEntityMappingImpl(signSite,rep);
  266. break;
  267. case Sign:
  268. sign = new DefaultSignImpl(signSite,rep);
  269. break;
  270. default:
  271. log.warn("Unsupported SignType "+signType.getUri()+" (create Sign instance). Please adapt this implementation!");
  272. sign = new DefaultSignImpl(signSite,rep);
  273. break;
  274. }
  275. return sign;
  276. }
  277. }