-
Notifications
You must be signed in to change notification settings - Fork 31
SlingModelPersist type handling cleanup #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ | |
| */ | ||
| package org.apache.sling.models.persistor.impl; | ||
|
|
||
| import com.drew.lang.annotations.NotNull; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment re:annotation |
||
| import java.lang.reflect.Field; | ||
| import java.lang.reflect.InvocationTargetException; | ||
| import java.lang.reflect.Method; | ||
|
|
@@ -42,7 +43,6 @@ | |
| import org.apache.sling.models.persistor.ModelPersistor; | ||
| import org.apache.sling.models.persistor.annotations.DirectDescendants; | ||
| import org.apache.sling.models.persistor.impl.util.ReflectionUtils; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.osgi.service.component.annotations.Component; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
@@ -112,12 +112,14 @@ public void persist(final @NotNull String nodePath, final @NotNull Object instan | |
| final ResourceTypeKey resourceType = ResourceTypeKey.fromObject(instance); | ||
|
|
||
| // let's create the resource first | ||
| LOGGER.debug("Creating node at: {} of type: {}", nodePath, resourceType.primaryType); | ||
| LOGGER.debug("Creating node at: {} of type: {}", nodePath, resourceType.nodeType); | ||
| boolean isUpdate = resourceResolver.getResource(nodePath) != null; | ||
| resource = ResourceUtil.getOrCreateResource(resourceResolver, nodePath, resourceType.primaryType, NT_UNSTRUCTURED, true); | ||
| if (StringUtils.isNotEmpty(resourceType.childType)) { | ||
| LOGGER.debug("Needs a child node, creating node at: {} of type: {}", nodePath, resourceType.childType); | ||
| resource = ResourceUtil.getOrCreateResource(resourceResolver, nodePath + "/" + JCR_CONTENT, resourceType.childType, NT_UNSTRUCTURED, true); | ||
| Map<String, Object> properties = new HashMap<>(); | ||
| properties.put("jcr:primaryType", resourceType.nodeType); | ||
|
|
||
| resource = ResourceUtil.getOrCreateResource(resourceResolver, nodePath, properties, NT_UNSTRUCTURED, true); | ||
| if (resourceType.resourceType != null) { | ||
| resource.adaptTo(ModifiableValueMap.class).put("sling:resourceType", resourceType.resourceType); | ||
| } | ||
|
|
||
| if (ReflectionUtils.isArrayOrCollection(instance)) { | ||
|
|
@@ -132,6 +134,7 @@ public void persist(final @NotNull String nodePath, final @NotNull Object instan | |
| fields.stream() | ||
| .filter(field -> ReflectionUtils.isNotTransient(field, isUpdate)) | ||
| .filter(field -> ReflectionUtils.isSupportedType(field) || ReflectionUtils.isCollectionOfPrimitiveType(field)) | ||
| // TODO: Be smarter about transient fields declared with Lombok | ||
| .filter(f -> ReflectionUtils.hasNoTransientGetter(f.getName(), instance.getClass())) | ||
| .forEach(field -> persistField(r, instance, field, deepPersist)); | ||
| } | ||
|
|
@@ -160,7 +163,9 @@ private void persistField(@NotNull Resource resource, @NotNull Object instance, | |
| Object value = ReflectionUtils.getStorableValue(field.get(instance)); | ||
|
|
||
| // remove the attribute that is null, or remove in case it changes type | ||
| values.remove(fieldName); | ||
| if (!fieldName.equals("jcr:primaryType")) { | ||
| values.remove(fieldName); | ||
| } | ||
| if (value != null) { | ||
| values.put(fieldName, value); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,10 +17,12 @@ | |
| * under the License. | ||
| */package org.apache.sling.models.persistor.impl; | ||
|
|
||
| import java.lang.reflect.Field; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import javax.inject.Named; | ||
| import org.apache.commons.lang3.reflect.FieldUtils; | ||
| import org.apache.sling.models.annotations.Model; | ||
| import org.apache.sling.models.persistor.annotations.ChildType; | ||
| import org.apache.sling.models.persistor.annotations.ResourceType; | ||
|
|
||
| import static org.apache.sling.models.persistor.impl.util.ReflectionUtils.getAnnotatedValue; | ||
|
|
@@ -33,15 +35,15 @@ public class ResourceTypeKey { | |
| static final Map<Class<?>, ResourceTypeKey> NODE_TYPE_FOR_CLASS = new HashMap<>(); | ||
| static public final ResourceTypeKey NT_UNSTRUCTURED = new ResourceTypeKey("nt:unstructured", null); | ||
|
|
||
| final public String primaryType; | ||
| final public String childType; | ||
| final public String nodeType; | ||
| final public String resourceType; | ||
|
|
||
| public ResourceTypeKey(String primaryType, String childType) { | ||
| this.primaryType = primaryType; | ||
| this.childType = childType; | ||
| public ResourceTypeKey(String nodeType, String resourceType) { | ||
| this.nodeType = nodeType != null ? nodeType : "nt:unstructured"; | ||
| this.resourceType = resourceType; | ||
| } | ||
|
|
||
| public static ResourceTypeKey fromObject(Object obj) { | ||
| public static ResourceTypeKey fromObject(Object obj) throws IllegalArgumentException, IllegalAccessException { | ||
| if (obj == null) { | ||
| return ResourceTypeKey.NT_UNSTRUCTURED; | ||
| } | ||
|
|
@@ -50,22 +52,34 @@ public static ResourceTypeKey fromObject(Object obj) { | |
| return NODE_TYPE_FOR_CLASS.get(obj.getClass()); | ||
| } | ||
|
|
||
| String nodeType = getNodeType(obj); | ||
| Model modelAnnotation = obj.getClass().getAnnotation(Model.class); | ||
| String primaryType = (String) getAnnotatedValue(obj, ResourceType.class); | ||
| String resourceType = (String) getAnnotatedValue(obj, ResourceType.class); | ||
|
|
||
| // Use the model annotation for resource type as needed | ||
| if (primaryType == null | ||
| if (resourceType == null | ||
| && modelAnnotation != null | ||
| && modelAnnotation.resourceType() != null | ||
| && modelAnnotation.resourceType().length == 1) { | ||
| primaryType = modelAnnotation.resourceType()[0]; | ||
| && modelAnnotation.resourceType().length >= 1) { | ||
| resourceType = modelAnnotation.resourceType()[0]; | ||
| } | ||
| String childType = (String) getAnnotatedValue(obj, ChildType.class); | ||
| if (primaryType != null) { | ||
| ResourceTypeKey key = new ResourceTypeKey(primaryType, childType); | ||
|
|
||
| if (nodeType != null || resourceType != null) { | ||
| ResourceTypeKey key = new ResourceTypeKey(nodeType, resourceType); | ||
| NODE_TYPE_FOR_CLASS.put(obj.getClass(), key); | ||
| return key; | ||
| } else { | ||
| return ResourceTypeKey.NT_UNSTRUCTURED; | ||
| } | ||
| } | ||
|
|
||
| private static String getNodeType(Object obj) throws IllegalArgumentException, IllegalAccessException { | ||
| for (Field f : obj.getClass().getDeclaredFields()) { | ||
| Named namedAnnotation = f.getAnnotation(Named.class); | ||
| if (namedAnnotation != null && namedAnnotation.value().equals("jcr:primaryType")) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agree, I try to avoid hard-coding too. Thanks for catching that. |
||
| return String.valueOf(FieldUtils.readField(f, obj, true)); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@badvision any particular reason for changing annotation types? A number of other projects use the Jetbrains annotations, so it'd be better to be consistent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm good point, I think that was an oversight as I was having difficulty building in this one case -- happy to revert them back.