Need to access TransformQuery.transform(CDAEntry entry)
Closed this issue · 1 comments
jmfayard commented
Bonjour,
In our codebase, we have some boring manual mapping functions like this one:
fun mapCDAEntryToEmployee(entry: CDAEntry): Employee {
return Employee(
id = entry.id(),
firstName = entry.getField("firstName") ?: String.EMPTY,
lastName = entry.getField("lastName") ?: String.EMPTY,
/// ...
)
}
That's because we need to call that outside of a TransformQuery
And TransformQuery
seems to be the only place where mapping from a CDAEntry to a POJO via annotations is available
contentful.java/src/main/java/com/contentful/java/cda/TransformQuery.java
Lines 349 to 465 in 05a3333
private Object transform(CDAEntry entry) { | |
final Object result; | |
if (!customClassByContentTypeIdCache.containsKey(entry.contentType().id())) { | |
return entry; | |
} | |
final Class<?> type = customClassByContentTypeIdCache.get(entry.contentType().id()); | |
if (instanceCache.containsKey(entry.id())) { | |
result = instanceCache.get(entry.id()); | |
} else { | |
try { | |
result = type.newInstance(); | |
} catch (Exception e) { | |
throw new IllegalStateException("Cannot transform entry " + entry + " to type " | |
+ type.getCanonicalName(), e); | |
} | |
instanceCache.put(entry.id(), result); | |
for (final Field field : type.getDeclaredFields()) { | |
final ContentfulField annotation = field.getAnnotation(ContentfulField.class); | |
if (annotation != null) { | |
transformFieldAnnotation(entry, result, field, annotation); | |
} else { | |
final ContentfulSystemField systemField = | |
field.getAnnotation(ContentfulSystemField.class); | |
if (systemField != null) { | |
transformSystemFieldAnnotation(entry, result, field, systemField); | |
} | |
} | |
} | |
} | |
return result; | |
} | |
private void transformFieldAnnotation( | |
CDAEntry entry, | |
Object result, | |
Field field, | |
ContentfulField annotation) { | |
final boolean wasAccessible = field.isAccessible(); | |
field.setAccessible(true); | |
final String key; | |
if (annotation.value().isEmpty()) { | |
key = field.getName(); | |
} else { | |
key = annotation.value(); | |
} | |
final String locale; | |
if (annotation.locale().isEmpty()) { | |
locale = entry.defaultLocale; | |
} else { | |
locale = annotation.locale(); | |
} | |
try { | |
final Object value = entry.getField(locale, key); | |
if (value instanceof CDAEntry) { | |
final CDAEntry fieldEntry = (CDAEntry) value; | |
if (!instanceCache.containsKey(fieldEntry.id())) { | |
transform(fieldEntry); | |
} | |
field.set(result, instanceCache.get(fieldEntry.id())); | |
} else if (value instanceof Collection) { | |
@SuppressWarnings("unchecked") final Collection<Object> collection = (Collection) value; | |
final ArrayList<Object> transformedList = new ArrayList<>(collection.size()); | |
for (final Object element : collection) { | |
if (element instanceof CDAEntry) { | |
final CDAEntry collectionEntry = (CDAEntry) element; | |
if (customClassByContentTypeIdCache.containsKey(collectionEntry.contentType().id())) { | |
transformedList.add(transform(collectionEntry)); | |
} else { | |
transformedList.add(element); | |
} | |
} else { | |
transformedList.add(element); | |
} | |
field.set(result, transformedList); | |
} | |
} else { | |
field.set(result, value); | |
} | |
} catch (IllegalAccessException e) { | |
throw new IllegalStateException("Cannot set custom field " + key + "."); | |
} finally { | |
field.setAccessible(wasAccessible); | |
} | |
} | |
private void transformSystemFieldAnnotation(CDAEntry entry, Object result, Field field, | |
ContentfulSystemField annotation) { | |
if (!field.isAccessible()) { | |
field.setAccessible(true); | |
} | |
final String key; | |
if (annotation.value().isEmpty()) { | |
key = field.getName(); | |
} else { | |
key = annotation.value(); | |
} | |
try { | |
field.set(result, entry.getAttribute(key)); | |
} catch (IllegalAccessException e) { | |
throw new IllegalStateException("Cannot set custom system field " + key + "."); | |
} | |
} | |
} |
Would it be possible to add a public API for that?
rafalniski commented
Hey @jmfayard ,
unfortunately, we don't have plans to make it a public API any time soon.