001: package org.ontoware.rdfreactor.runtime;
002:
003: import java.lang.reflect.Constructor;
004: import java.util.HashMap;
005: import java.util.Map;
006:
007: import org.ontoware.rdf2go.exception.ModelRuntimeException;
008: import org.ontoware.rdf2go.model.Model;
009: import org.ontoware.rdf2go.model.node.BlankNode;
010: import org.ontoware.rdf2go.model.node.Node;
011: import org.ontoware.rdf2go.model.node.Resource;
012: import org.ontoware.rdf2go.model.node.URI;
013: import org.ontoware.rdfreactor.runtime.converter.BooleanConverter;
014: import org.ontoware.rdfreactor.runtime.converter.ByteConverter;
015: import org.ontoware.rdfreactor.runtime.converter.CalendarConverter;
016: import org.ontoware.rdfreactor.runtime.converter.DoubleConverter;
017: import org.ontoware.rdfreactor.runtime.converter.FloatConverter;
018: import org.ontoware.rdfreactor.runtime.converter.IntegerConverter;
019: import org.ontoware.rdfreactor.runtime.converter.JavaNetUriConverter;
020: import org.ontoware.rdfreactor.runtime.converter.LongConverter;
021: import org.ontoware.rdfreactor.runtime.converter.NodeConverter;
022: import org.ontoware.rdfreactor.runtime.converter.ResourceConverter;
023: import org.ontoware.rdfreactor.runtime.converter.ShortConverter;
024: import org.ontoware.rdfreactor.runtime.converter.StringConverter;
025: import org.ontoware.rdfreactor.runtime.converter.UriConverter;
026: import org.ontoware.rdfreactor.runtime.converter.UrlConverter;
027: import org.slf4j.Logger;
028: import org.slf4j.LoggerFactory;
029:
030: public class RDFReactorRuntime {
031:
032: static Logger log = LoggerFactory
033: .getLogger(RDFReactorRuntime.class);
034:
035: private static Map<Class<?>, INodeConverter<?>> map = new HashMap<Class<?>, INodeConverter<?>>();
036:
037: static {
038: // rdf2go types
039: registerConverter(org.ontoware.rdf2go.model.node.Node.class,
040: new NodeConverter());
041: registerConverter(
042: org.ontoware.rdf2go.model.node.Resource.class,
043: new ResourceConverter());
044: registerConverter(org.ontoware.rdf2go.model.node.URI.class,
045: new UriConverter());
046:
047: // primitive data types
048: registerConverter(String.class, new StringConverter());
049: registerConverter(Boolean.class, new BooleanConverter());
050: registerConverter(Byte.class, new ByteConverter());
051: registerConverter(Short.class, new ShortConverter());
052: registerConverter(Integer.class, new IntegerConverter());
053: registerConverter(Long.class, new LongConverter());
054: registerConverter(Float.class, new FloatConverter());
055: registerConverter(Double.class, new DoubleConverter());
056: registerConverter(java.net.URI.class, new JavaNetUriConverter());
057: registerConverter(java.net.URL.class, new UrlConverter());
058: registerConverter(java.util.Calendar.class,
059: new CalendarConverter());
060: }
061:
062: public static void registerConverter(Class<?> type,
063: INodeConverter<?> converter) {
064: map.put(type, converter);
065: }
066:
067: public static INodeConverter<?> getConverter(Class<?> type) {
068: return map.get(type);
069: }
070:
071: // /////////////////////
072: // type conversion
073:
074: /**
075: * Convert RDF entities to ReactorBaseNamed and primitive java values. This
076: * is the main method for calling other converter methods.
077: *
078: * @param model -
079: * the underlying RDF2Go model
080: * @param n -
081: * convert this object. type may be: URI, BlankNode,
082: * LanguageTagLiteral, DatatypeLiteral, String
083: * @param returnType -
084: * n is converted to this type, if it implements the needed
085: * constructor
086: * @return a single object of returnType converted from n
087: * @throws ModelRuntimeException
088: */
089: @Patrolled
090: public static Object node2javatype(Model model, Node n,
091: java.lang.Class<?> returnType) throws ModelRuntimeException {
092: if (returnType.isArray())
093: // TODO call this method for each array member
094: throw new IllegalArgumentException(
095: "targetType may not be an array");
096:
097: INodeConverter<?> nodeConverter = RDFReactorRuntime
098: .getConverter(returnType);
099: if (nodeConverter == null) {
100: // // requested an RDFReactor generated subtype?
101: // if (ReflectionUtils.hasSuperClass(returnType, ReactorBase.class))
102: // {
103: return RDFReactorRuntime.resource2reactorbase(model, n,
104: returnType);
105: // } else {
106: // throw new RuntimeException(
107: // "RDFReactor cannot convert any RDF node to "
108: // + returnType + ". RDF node: " + n + " of type "
109: // + n.getClass());
110: // }
111: } else {
112: return nodeConverter.toJava(n);
113: }
114:
115: }
116:
117: /**
118: * Convert an RDF2Go resource to the target type, which must be a subclass
119: * of ReactorBase.
120: *
121: * @param model -
122: * the underlying RDF2Go model
123: * @param node -
124: * convert this object, can be a URI or a BlankNode
125: * @param targetType -
126: * used to find constructor for creating the returned object. has
127: * to implement the following constructor c: <br>
128: * o is URI: c(Model, URI, boolean) or c(Model, Object, boolean)
129: * <br>
130: * o is BlankNode: c(Model, BlankNode) or c(Model, BlankNode)
131: * <br>
132: * @return object of the given target type with contents of given object
133: */
134: public static Object resource2reactorbase(Model model, Node node,
135: Class<?> targetType) {
136: if (targetType.isArray())
137: throw new IllegalArgumentException(
138: "targetType may not be an array");
139:
140: if (node instanceof URI) {
141: log.debug("URI node");
142: try {
143:
144: // // TODO: experimental
145: // URI classURI = (URI)
146: // targetType.getDeclaredField("RDFS_CLASS")
147: // .get(null);
148:
149: Constructor<?> constructor;
150: try {
151: constructor = targetType
152: .getConstructor(new java.lang.Class[] {
153: Model.class, URI.class,
154: boolean.class });
155: } catch (NoSuchMethodException nsme) {
156: constructor = targetType
157: .getConstructor(new java.lang.Class[] {
158: Model.class, Resource.class,
159: boolean.class });
160: }
161:
162: return (Object) constructor.newInstance(new Object[] {
163: model, node, false });
164:
165: } catch (ClassCastException cce) {
166: throw new RuntimeException(cce);
167: } catch (NoSuchMethodException nsme) {
168: throw new RuntimeException("found no constructor "
169: + targetType
170: + "(Model, URI/Resource, boolean) " + nsme);
171: } catch (Exception e) {
172: throw new ConversionException(e);
173: }
174: } else if (node instanceof BlankNode) {
175: log.debug("BlankNode node");
176: Constructor<?> constructor;
177: try {
178: try {
179: constructor = targetType
180: .getConstructor(new java.lang.Class[] {
181: Model.class, BlankNode.class,
182: boolean.class });
183: } catch (NoSuchMethodException nsme) {
184: log.debug("Class " + targetType
185: + " has no constructor for BlankNode");
186: constructor = targetType
187: .getConstructor(new java.lang.Class[] {
188: Model.class, Resource.class,
189: boolean.class });
190: }
191: BlankNode bnode = (BlankNode) node;
192: return (Object) constructor.newInstance(new Object[] {
193: model, bnode, false });
194: } catch (ClassCastException cce) {
195: throw new RuntimeException(cce);
196: } catch (NoSuchMethodException nsme) {
197: throw new RuntimeException("found no constructor "
198: + targetType
199: + "(Model, BlankNode/Resource, boolean) "
200: + nsme);
201: } catch (Exception e) {
202: throw new ConversionException(e);
203: }
204:
205: } else if (node == null) {
206: return null;
207: } else {
208: throw new RuntimeException("cannot convert " + node
209: + " of class <" + node.getClass() + "> from "
210: + node + " and convert it to " + targetType);
211: }
212:
213: }
214:
215: /**
216: * Work around a nasty issue in RepositoryModel: One cannot add a Resource to anything
217: * It must either be a BlankNode OR a URI.
218: * @param model
219: * @param o
220: * @return
221: */
222: public static Resource genericResource2RDF2Goresource(Model model,
223: Resource o) {
224: if (o instanceof ReactorRuntimeEntity) {
225: log
226: .debug("object is an instanceof ReactorBase, so will add as single resource");
227: // add as resource
228: Resource objectID = ((ReactorRuntimeEntity) o)
229: .getResource();
230: return objectID;
231: } else {
232: return o;
233: }
234: }
235:
236: /**
237: * @param model
238: * @param reactorValue
239: * @return a single RDF2Go Node from a Java object
240: */
241: public static Node java2node(Model model, Object reactorValue) {
242: if (reactorValue == null) {
243: throw new IllegalArgumentException(
244: "Argument may not be null");
245: }
246:
247: // convert value to rdfnode
248: log.debug("value is instance of "
249: + reactorValue.getClass().getName());
250: if (reactorValue instanceof ReactorRuntimeEntity) {
251: log
252: .debug("object is an instanceof ReactorBase, so will add as single resource");
253: // add as resource
254: Resource objectID = ((ReactorRuntimeEntity) reactorValue)
255: .getResource();
256: return objectID;
257: } else {
258: for (Class<?> clazz : map.keySet()) {
259: log.debug("Can a " + reactorValue.getClass()
260: + " be converted as " + clazz + " ?");
261: if (clazz.isInstance(reactorValue)) {
262: log.debug("Yes");
263: return getConverter(clazz).toNode(model,
264: reactorValue);
265: }
266: }
267: }
268:
269: throw new ConversionException(
270: "Cannot handle instances of "
271: + reactorValue.getClass()
272: + " which are neither instance of Reactorbase nor Reactorbase[]");
273: }
274:
275: }
|