diff --git a/crnk-core/src/main/java/io/crnk/core/engine/internal/document/mapper/DocumentMapperUtil.java b/crnk-core/src/main/java/io/crnk/core/engine/internal/document/mapper/DocumentMapperUtil.java index a32728760..6e1627330 100644 --- a/crnk-core/src/main/java/io/crnk/core/engine/internal/document/mapper/DocumentMapperUtil.java +++ b/crnk-core/src/main/java/io/crnk/core/engine/internal/document/mapper/DocumentMapperUtil.java @@ -61,14 +61,15 @@ public DocumentMapperUtil(ResourceRegistry resourceRegistry, ObjectMapper object serializerUtil = new SerializerUtil(serializeLinksAsObjects); } - protected static List getRequestedFields(ResourceInformation resourceInformation, QueryAdapter queryAdapter, + protected List getRequestedFields(ResourceInformation resourceInformation, QueryAdapter queryAdapter, List fields, boolean relation) { Map> includedFieldsSet = queryAdapter != null ? queryAdapter.getIncludedFields() : null; final Set includedFields = new HashSet<>(); - if (includedFieldsSet != null) { - addIfNotNull(includedFields, includedFieldsSet.get(resourceInformation.getResourceType())); - addIfNotNull(includedFields, includedFieldsSet.get(resourceInformation.getSuperResourceType())); + RegistryEntry entry = resourceRegistry.getEntry(resourceInformation.getResourceType()); + while(entry != null){ + addIfNotNull(includedFields, includedFieldsSet.get(entry.getResourceInformation().getResourceType())); + entry = entry.getParentRegistryEntry(); } if (noResourceIncludedFieldsSpecified(includedFields)) { return fields; diff --git a/crnk-core/src/main/java/io/crnk/core/engine/internal/document/mapper/ResourceMapper.java b/crnk-core/src/main/java/io/crnk/core/engine/internal/document/mapper/ResourceMapper.java index 6c581a484..6c9287e4f 100644 --- a/crnk-core/src/main/java/io/crnk/core/engine/internal/document/mapper/ResourceMapper.java +++ b/crnk-core/src/main/java/io/crnk/core/engine/internal/document/mapper/ResourceMapper.java @@ -115,8 +115,7 @@ public LinksInformation getResourceLinks(Object entity, ResourceInformation reso protected void setAttributes(Resource resource, Object entity, ResourceInformation resourceInformation, QueryAdapter queryAdapter, ResourceMappingConfig mappingConfig) { // fields legacy may further limit the number of fields - List fields = DocumentMapperUtil - .getRequestedFields(resourceInformation, queryAdapter, resourceInformation.getAttributeFields(), false); + List fields = util.getRequestedFields(resourceInformation, queryAdapter, resourceInformation.getAttributeFields(), false); // serialize the individual attributes QueryContext queryContext = queryAdapter.getQueryContext(); for (ResourceField field : fields) { @@ -201,8 +200,7 @@ private boolean isValueIncluded(ResourceField field, Object value) { protected void setRelationships(Resource resource, Object entity, ResourceInformation resourceInformation, QueryAdapter queryAdapter, ResourceMappingConfig mappingConfig) { - List fields = DocumentMapperUtil - .getRequestedFields(resourceInformation, queryAdapter, resourceInformation.getRelationshipFields(), true); + List fields = util.getRequestedFields(resourceInformation, queryAdapter, resourceInformation.getRelationshipFields(), true); QueryContext queryContext = queryAdapter.getQueryContext(); for (ResourceField field : fields) { if (!isIgnored(field, queryContext)) { diff --git a/crnk-core/src/test/java/io/crnk/core/CoreTestModule.java b/crnk-core/src/test/java/io/crnk/core/CoreTestModule.java index b2584ff64..e097b631e 100644 --- a/crnk-core/src/test/java/io/crnk/core/CoreTestModule.java +++ b/crnk-core/src/test/java/io/crnk/core/CoreTestModule.java @@ -14,7 +14,7 @@ import io.crnk.core.mock.repository.RelationIdTestRepository; import io.crnk.core.mock.repository.RelationshipBehaviorTestRepository; import io.crnk.core.mock.repository.ScheduleRepositoryImpl; -import io.crnk.core.mock.repository.SuperTaskRepository; +import io.crnk.core.mock.repository.TopTaskRepository; import io.crnk.core.mock.repository.TaskRepository; import io.crnk.core.mock.repository.TaskToProjectRepository; import io.crnk.core.mock.repository.TaskWithLookupRepository; @@ -39,12 +39,12 @@ public void setupModule(ModuleContext context) { context.addRepository(new ProjectToTaskRepository()); context.addRepository(new ProjectPolymorphicRepository()); context.addRepository(new ScheduleRepositoryImpl()); - context.addRepository(new SuperTaskRepository()); context.addRepository(new ThingRepository()); context.addRepository(new TaskRepository()); context.addRepository(new TaskToProjectRepository()); context.addRepository(new TaskWithLookupRepository()); context.addRepository(new TaskWithLookupToProjectRepository()); + context.addRepository(new TopTaskRepository()); context.addRepository(new UserRepository()); context.addRepository(new UserToProjectRepository()); context.addRepository(new UserToTaskRepository()); diff --git a/crnk-core/src/test/java/io/crnk/core/engine/internal/document/mapper/DocumentMapperTest.java b/crnk-core/src/test/java/io/crnk/core/engine/internal/document/mapper/DocumentMapperTest.java index 5a3b8fb38..a1ee51a44 100644 --- a/crnk-core/src/test/java/io/crnk/core/engine/internal/document/mapper/DocumentMapperTest.java +++ b/crnk-core/src/test/java/io/crnk/core/engine/internal/document/mapper/DocumentMapperTest.java @@ -16,18 +16,20 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.node.ObjectNode; + import io.crnk.core.engine.document.Document; import io.crnk.core.engine.document.ErrorData; import io.crnk.core.engine.document.Relationship; import io.crnk.core.engine.document.Resource; import io.crnk.core.engine.document.ResourceIdentifier; import io.crnk.core.engine.query.QueryAdapter; +import io.crnk.core.mock.models.BottomTask; import io.crnk.core.mock.models.LazyTask; +import io.crnk.core.mock.models.MiddleTask; import io.crnk.core.mock.models.Project; import io.crnk.core.mock.models.Schedule; -import io.crnk.core.mock.models.SpecialTask; -import io.crnk.core.mock.models.SuperTask; import io.crnk.core.mock.models.Task; +import io.crnk.core.mock.models.TopTask; import io.crnk.core.queryspec.PathSpec; import io.crnk.core.queryspec.QuerySpec; import io.crnk.core.queryspec.internal.QuerySpecAdapter; @@ -43,6 +45,7 @@ import org.junit.Test; import org.mockito.Mockito; + public class DocumentMapperTest extends AbstractDocumentMapperTest { @Test @@ -650,25 +653,37 @@ public void testAttributesSelection() { @Test public void testSupertypeAttributesSelection() { - SpecialTask task = createSpecialTask(2, "sample task"); + BottomTask task = createTreeTask(2, "sample task"); task.setEnd("next month"); + task.setRecurring(true); + task.setPublicComment("public"); + task.setPrivateComment("private"); + JsonApiResponse response = new JsonApiResponse(); response.setEntity(task); - QuerySpec querySpec = new QuerySpec(SpecialTask.class); - querySpec.includeField(PathSpec.of("end")); - final QuerySpec superQuerySpec = new QuerySpec(SuperTask.class); - superQuerySpec.includeField(PathSpec.of("name")); - querySpec.setNestedSpecs(Collections.singletonList(superQuerySpec)); + QuerySpec bottomQuerySpec = new QuerySpec(BottomTask.class); + bottomQuerySpec.includeField(PathSpec.of("end")); + QuerySpec middleQuerySpec = new QuerySpec(MiddleTask.class); + middleQuerySpec.includeField(PathSpec.of("publicComment")); + final QuerySpec topQuerySpec = new QuerySpec(TopTask.class); + topQuerySpec.includeField(PathSpec.of("name")); - Document document = mapper.toDocument(response, toAdapter(querySpec), mappingConfig).get(); + bottomQuerySpec.setNestedSpecs(Arrays.asList(topQuerySpec, middleQuerySpec)); + + Document document = mapper.toDocument(response, toAdapter(bottomQuerySpec), mappingConfig).get(); Resource resource = document.getSingleData().get(); Assert.assertEquals("2", resource.getId()); - Assert.assertEquals("specialTask", resource.getType()); + Assert.assertEquals("bottomTask", resource.getType()); Assert.assertNull(resource.getAttributes().get("category")); Assert.assertNull(resource.getAttributes().get("recurring")); + Assert.assertNull(resource.getAttributes().get("privateComment")); + Assert.assertNotNull(resource.getAttributes().get("name")); + Assert.assertNotNull(resource.getAttributes().get("end")); + Assert.assertNotNull(resource.getAttributes().get("publicComment")); Assert.assertEquals("sample task", resource.getAttributes().get("name").asText()); Assert.assertEquals("next month", resource.getAttributes().get("end").asText()); + Assert.assertEquals("public", resource.getAttributes().get("publicComment").asText()); } @Test @@ -713,8 +728,8 @@ private LazyTask createLazyTask(long id) { return task; } - private SpecialTask createSpecialTask(long id, String name) { - SpecialTask task = new SpecialTask(); + private BottomTask createTreeTask(long id, String name) { + BottomTask task = new BottomTask(); task.setId(id); task.setName(name); return task; diff --git a/crnk-core/src/test/java/io/crnk/core/mock/models/SpecialTask.java b/crnk-core/src/test/java/io/crnk/core/mock/models/BottomTask.java similarity index 77% rename from crnk-core/src/test/java/io/crnk/core/mock/models/SpecialTask.java rename to crnk-core/src/test/java/io/crnk/core/mock/models/BottomTask.java index 63aaf8ae5..5537001b7 100644 --- a/crnk-core/src/test/java/io/crnk/core/mock/models/SpecialTask.java +++ b/crnk-core/src/test/java/io/crnk/core/mock/models/BottomTask.java @@ -2,8 +2,8 @@ import io.crnk.core.resource.annotations.JsonApiResource; -@JsonApiResource(type = "specialTask", resourcePath = "superTasks") -public class SpecialTask extends SuperTask { +@JsonApiResource(type = "bottomTask", resourcePath = "treeTasks") +public class BottomTask extends MiddleTask { private boolean recurring; diff --git a/crnk-core/src/test/java/io/crnk/core/mock/models/MiddleTask.java b/crnk-core/src/test/java/io/crnk/core/mock/models/MiddleTask.java new file mode 100644 index 000000000..099cd2c65 --- /dev/null +++ b/crnk-core/src/test/java/io/crnk/core/mock/models/MiddleTask.java @@ -0,0 +1,27 @@ +package io.crnk.core.mock.models; + +import io.crnk.core.resource.annotations.JsonApiResource; + +@JsonApiResource(type = "middleTask", subTypes = BottomTask.class, resourcePath = "treeTasks") +public abstract class MiddleTask extends TopTask { + + private String publicComment; + + private String privateComment; + + public String getPublicComment() { + return publicComment; + } + + public void setPublicComment(final String publicComment) { + this.publicComment = publicComment; + } + + public String getPrivateComment() { + return privateComment; + } + + public void setPrivateComment(final String privateComment) { + this.privateComment = privateComment; + } +} \ No newline at end of file diff --git a/crnk-core/src/test/java/io/crnk/core/mock/models/SuperTask.java b/crnk-core/src/test/java/io/crnk/core/mock/models/TopTask.java similarity index 78% rename from crnk-core/src/test/java/io/crnk/core/mock/models/SuperTask.java rename to crnk-core/src/test/java/io/crnk/core/mock/models/TopTask.java index 5896a0bc0..bb8a77df0 100644 --- a/crnk-core/src/test/java/io/crnk/core/mock/models/SuperTask.java +++ b/crnk-core/src/test/java/io/crnk/core/mock/models/TopTask.java @@ -3,8 +3,8 @@ import io.crnk.core.resource.annotations.JsonApiId; import io.crnk.core.resource.annotations.JsonApiResource; -@JsonApiResource(type = "superTasks", subTypes = SpecialTask.class) -public abstract class SuperTask { +@JsonApiResource(type = "topTask", subTypes = MiddleTask.class, resourcePath = "treeTasks") +public abstract class TopTask { @JsonApiId private Long id; @@ -17,7 +17,7 @@ public Long getId() { return id; } - public SuperTask setId(Long id) { + public TopTask setId(Long id) { this.id = id; return this; } diff --git a/crnk-core/src/test/java/io/crnk/core/mock/repository/SuperTaskRepository.java b/crnk-core/src/test/java/io/crnk/core/mock/repository/SuperTaskRepository.java deleted file mode 100644 index 7196aeb30..000000000 --- a/crnk-core/src/test/java/io/crnk/core/mock/repository/SuperTaskRepository.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.crnk.core.mock.repository; - -import java.util.HashSet; -import java.util.Set; - -import io.crnk.core.mock.models.SpecialTask; -import io.crnk.core.mock.models.SuperTask; -import io.crnk.core.queryspec.QuerySpec; -import io.crnk.core.repository.ReadOnlyResourceRepositoryBase; -import io.crnk.core.resource.list.ResourceList; - -public class SuperTaskRepository extends ReadOnlyResourceRepositoryBase { - - private Set tasks = new HashSet<>(); - - private long nextId = 0; - - public SuperTaskRepository() { - super(SuperTask.class); - } - - @Override - public ResourceList findAll(final QuerySpec querySpec) { - return null; - } -} \ No newline at end of file diff --git a/crnk-core/src/test/java/io/crnk/core/mock/repository/TopTaskRepository.java b/crnk-core/src/test/java/io/crnk/core/mock/repository/TopTaskRepository.java new file mode 100644 index 000000000..cf53e61e0 --- /dev/null +++ b/crnk-core/src/test/java/io/crnk/core/mock/repository/TopTaskRepository.java @@ -0,0 +1,18 @@ +package io.crnk.core.mock.repository; + +import io.crnk.core.mock.models.TopTask; +import io.crnk.core.queryspec.QuerySpec; +import io.crnk.core.repository.ReadOnlyResourceRepositoryBase; +import io.crnk.core.resource.list.ResourceList; + +public class TopTaskRepository extends ReadOnlyResourceRepositoryBase { + + public TopTaskRepository() { + super(TopTask.class); + } + + @Override + public ResourceList findAll(final QuerySpec querySpec) { + return null; + } +} \ No newline at end of file