in taverna-reference-impl/src/main/java/org/apache/taverna/reference/impl/ReferenceServiceImpl.java [147:343]
private T2Reference getNameForObject(Object o, int currentDepth,
boolean useConverterSPI, ReferenceContext context)
throws ReferenceServiceException {
if (currentDepth < 0)
throw new ReferenceServiceException("Cannot register at depth "
+ currentDepth + ": " + o);
/*
* First check whether this is an Identified, and if so whether it
* already has an ID. If this is the case then return it, we assume that
* anything which has an identifier already allocated must have been
* registered (this is implicit in the contract for the various
* sub-services
*/
if (o instanceof Identified) {
Identified i = (Identified) o;
if (i.getId() != null)
return i.getId();
}
/*
* Then check whether the item *is* a T2Reference, in which case we can
* just return it (useful for when registering lists of existing
* references)
*/
if (o instanceof T2Reference)
return (T2Reference) o;
if (o.getClass().isArray()) {
Class<?> elementType = o.getClass().getComponentType();
if (elementType.getCanonicalName().equals("char")) {
char[] cArray = (char[]) o;
List<Character> cList = new ArrayList<>();
for (char c : cArray)
cList.add(new Character(c));
o = cList;
} else if (elementType.getCanonicalName().equals("short")) {
short[] cArray = (short[]) o;
List<Short> cList = new ArrayList<>();
for (short c : cArray)
cList.add(new Short(c));
o = cList;
} else if (elementType.getCanonicalName().equals("int")) {
int[] cArray = (int[]) o;
List<Integer> cList = new ArrayList<>();
for (int c : cArray)
cList.add(new Integer(c));
o = cList;
} else if (elementType.getCanonicalName().equals("long")) {
long[] cArray = (long[]) o;
List<Long> cList = new ArrayList<>();
for (long c : cArray)
cList.add(new Long(c));
o = cList;
} else if (elementType.getCanonicalName().equals("float")) {
float[] cArray = (float[]) o;
List<Float> cList = new ArrayList<>();
for (float c : cArray)
cList.add(new Float(c));
o = cList;
} else if (elementType.getCanonicalName().equals("double")) {
double[] cArray = (double[]) o;
List<Double> cList = new ArrayList<>();
for (double c : cArray)
cList.add(new Double(c));
o = cList;
} else if (elementType.getCanonicalName().equals("boolean")) {
boolean[] cArray = (boolean[]) o;
List<Boolean> cList = new ArrayList<>();
for (boolean c : cArray)
cList.add(new Boolean(c));
o = cList;
} else if (!elementType.getCanonicalName().equals("byte")) {
// Covert arrays of objects
Object[] cArray = (Object[]) o;
List<Object> cList = new ArrayList<>();
for (Object c : cArray)
cList.add(c);
o = cList;
}
}
// If a Collection but not a List
if ((o instanceof Collection) && !(o instanceof List)) {
List<Object> cList = new ArrayList<>();
cList.addAll((Collection<Object>) o);
o = cList;
}
// Next check lists.
if (o instanceof List) {
if (currentDepth < 1)
throw new ReferenceServiceException(
"Cannot register list at depth " + currentDepth);
List<?> l = (List<?>) o;
/*
* If the list is empty then register a new empty list of the
* appropriate depth and return it
*/
if (l.isEmpty())
try {
return listService.registerEmptyList(currentDepth, context)
.getId();
} catch (ListServiceException lse) {
throw new ReferenceServiceException(lse);
}
/*
* Otherwise construct a new list of T2Reference and register it,
* calling the getNameForObject method on all children of the list
* to construct the list of references
*/
else {
List<T2Reference> references = new ArrayList<>();
for (Object item : l)
/*
* Recursively call this method with a depth one lower than
* the current depth
*/
references.add(getNameForObject(item, currentDepth - 1,
useConverterSPI, context));
try {
return listService.registerList(references, context)
.getId();
} catch (ListServiceException lse) {
throw new ReferenceServiceException(lse);
}
}
} else {
/*
* Neither a list nor an already identified object, first thing is
* to engage the converters if enabled. Only engage if we don't
* already have a Throwable or an ExternalReferenceSPI instance
*/
if (useConverterSPI && (o instanceof Throwable == false)
&& (o instanceof ExternalReferenceSPI == false)) {
if (currentDepth != 0)
throw new ReferenceServiceException(
"Cannot register object " + o + " at depth "
+ currentDepth);
for (ValueToReferenceConverterSPI converter : converters)
if (converter.canConvert(o, context))
try {
o = converter.convert(o, context);
break;
} catch (ValueToReferenceConversionException vtrce) {
/*
* Fail, but that doesn't matter at the moment as
* there may be more converters to try.
*
* TODO - log this!
*/
}
}
/*
* If the object is neither a Throwable nor an ExternalReferenceSPI
* instance at this point we should fail the registration process,
* this means either that the conversion process wasn't enabled or
* that it failed to map the object type correctly.
*/
if (!(o instanceof Throwable)
&& !(o instanceof ExternalReferenceSPI))
throw new ReferenceServiceException(
"Failed to register object "
+ o
+ ", found a type '"
+ o.getClass().getCanonicalName()
+ "' which cannot currently be registered with the reference manager");
// Have either a Throwable or an ExternalReferenceSPI
if (o instanceof Throwable)
// Wrap in an ErrorDocument and return the ID
try {
ErrorDocument doc = errorDocumentService.registerError(
(Throwable) o, currentDepth, context);
return doc.getId();
} catch (ErrorDocumentServiceException edse) {
throw new ReferenceServiceException(edse);
}
if (o instanceof ExternalReferenceSPI) {
if (currentDepth != 0)
throw new ReferenceServiceException(
"Cannot register external references at depth "
+ currentDepth);
try {
Set<ExternalReferenceSPI> references = new HashSet<ExternalReferenceSPI>();
references.add((ExternalReferenceSPI) o);
ReferenceSet rs = referenceSetService.registerReferenceSet(
references, context);
return rs.getId();
} catch (ReferenceSetServiceException rsse) {
throw new ReferenceServiceException(rsse);
}
}
}
throw new ReferenceServiceException(
"Should never see this, reference registration"
+ " logic has fallen off the end of the"
+ " world, check the code!");
}