Skip to content
Snippets Groups Projects
Commit ae0c83c6 authored by Daniel Gerhardt's avatar Daniel Gerhardt
Browse files

Refactor and fix sub type handling for Content and Answer

We now use the format property instead as type ID for Jackson. A custom
TypeIdResolver is used for the mapping.
parent 68b36a5e
1 merge request!89Foundation for development of version 3.0
...@@ -2,6 +2,8 @@ package de.thm.arsnova.entities; ...@@ -2,6 +2,8 @@ package de.thm.arsnova.entities;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
import de.thm.arsnova.entities.serialization.FormatAnswerTypeIdResolver;
import de.thm.arsnova.entities.serialization.View; import de.thm.arsnova.entities.serialization.View;
import org.springframework.core.style.ToStringCreator; import org.springframework.core.style.ToStringCreator;
...@@ -9,14 +11,17 @@ import java.util.Map; ...@@ -9,14 +11,17 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
@JsonTypeInfo( @JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, use = JsonTypeInfo.Id.CUSTOM,
include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "format",
property = "type" visible = true,
defaultImpl = Answer.class
) )
public abstract class Answer extends Entity { @JsonTypeIdResolver(FormatAnswerTypeIdResolver.class)
public class Answer extends Entity {
private String contentId; private String contentId;
private String roomId; private String roomId;
private String creatorId; private String creatorId;
private Content.Format format;
private int round; private int round;
private Map<String, Map<String, ?>> extensions; private Map<String, Map<String, ?>> extensions;
...@@ -49,6 +54,16 @@ public abstract class Answer extends Entity { ...@@ -49,6 +54,16 @@ public abstract class Answer extends Entity {
this.creatorId = creatorId; this.creatorId = creatorId;
} }
@JsonView({View.Persistence.class, View.Public.class})
public Content.Format getFormat() {
return format;
}
@JsonView({View.Persistence.class, View.Public.class})
public void setFormat(final Content.Format format) {
this.format = format;
}
@JsonView({View.Persistence.class, View.Public.class}) @JsonView({View.Persistence.class, View.Public.class})
public int getRound() { public int getRound() {
return round; return round;
...@@ -69,6 +84,12 @@ public abstract class Answer extends Entity { ...@@ -69,6 +84,12 @@ public abstract class Answer extends Entity {
this.extensions = extensions; this.extensions = extensions;
} }
@JsonView(View.Persistence.class)
@Override
public Class<? extends Entity> getType() {
return Answer.class;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
...@@ -97,6 +118,7 @@ public abstract class Answer extends Entity { ...@@ -97,6 +118,7 @@ public abstract class Answer extends Entity {
.append("contentId", contentId) .append("contentId", contentId)
.append("roomId", roomId) .append("roomId", roomId)
.append("creatorId", creatorId) .append("creatorId", creatorId)
.append("format", format)
.append("round", round); .append("round", round);
} }
} }
...@@ -2,6 +2,8 @@ package de.thm.arsnova.entities; ...@@ -2,6 +2,8 @@ package de.thm.arsnova.entities;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
import de.thm.arsnova.entities.serialization.FormatContentTypeIdResolver;
import de.thm.arsnova.entities.serialization.View; import de.thm.arsnova.entities.serialization.View;
import org.springframework.core.style.ToStringCreator; import org.springframework.core.style.ToStringCreator;
...@@ -12,10 +14,12 @@ import java.util.Objects; ...@@ -12,10 +14,12 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
@JsonTypeInfo( @JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, use = JsonTypeInfo.Id.CUSTOM,
include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "format",
property = "type" visible = true,
defaultImpl = Content.class
) )
@JsonTypeIdResolver(FormatContentTypeIdResolver.class)
public class Content extends Entity { public class Content extends Entity {
public enum Format { public enum Format {
CHOICE, CHOICE,
...@@ -227,6 +231,12 @@ public class Content extends Entity { ...@@ -227,6 +231,12 @@ public class Content extends Entity {
this.abstentionsAllowed = abstentionsAllowed; this.abstentionsAllowed = abstentionsAllowed;
} }
@JsonView(View.Persistence.class)
@Override
public Class<? extends Entity> getType() {
return Content.class;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
......
...@@ -17,14 +17,8 @@ ...@@ -17,14 +17,8 @@
*/ */
package de.thm.arsnova.entities.serialization; package de.thm.arsnova.entities.serialization;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.module.SimpleModule;
import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.ChoiceAnswer;
import de.thm.arsnova.entities.ChoiceQuestionContent;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Entity; import de.thm.arsnova.entities.Entity;
import de.thm.arsnova.entities.TextAnswer;
public class CouchDbDocumentModule extends SimpleModule { public class CouchDbDocumentModule extends SimpleModule {
public CouchDbDocumentModule() { public CouchDbDocumentModule() {
...@@ -35,11 +29,5 @@ public class CouchDbDocumentModule extends SimpleModule { ...@@ -35,11 +29,5 @@ public class CouchDbDocumentModule extends SimpleModule {
public void setupModule(SetupContext context) { public void setupModule(SetupContext context) {
context.setMixInAnnotations(Entity.class, CouchDbDocumentMixIn.class); context.setMixInAnnotations(Entity.class, CouchDbDocumentMixIn.class);
context.setMixInAnnotations(de.thm.arsnova.entities.migration.v2.Entity.class, CouchDbDocumentV2MixIn.class); context.setMixInAnnotations(de.thm.arsnova.entities.migration.v2.Entity.class, CouchDbDocumentV2MixIn.class);
context.registerSubtypes(
new NamedType(Content.class, Content.class.getSimpleName()),
new NamedType(ChoiceQuestionContent.class, ChoiceQuestionContent.class.getSimpleName()),
new NamedType(Answer.class, Answer.class.getSimpleName()),
new NamedType(ChoiceAnswer.class, ChoiceAnswer.class.getSimpleName()),
new NamedType(TextAnswer.class, TextAnswer.class.getSimpleName()));
} }
} }
package de.thm.arsnova.entities.serialization;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.DatabindContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
import com.fasterxml.jackson.databind.type.TypeFactory;
import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.ChoiceAnswer;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.TextAnswer;
import java.io.IOException;
public class FormatAnswerTypeIdResolver extends TypeIdResolverBase {
@Override
public String idFromValue(final Object value) {
if (value instanceof Answer) {
return ((Answer) value).getFormat().toString();
} else {
throw new IllegalArgumentException("Unsupported type.");
}
}
@Override
public String idFromValueAndType(final Object value, final Class<?> suggestedType) {
return idFromValue(value);
}
@Override
public JavaType typeFromId(final DatabindContext context, final String id) throws IOException {
Content.Format format = Content.Format.valueOf(id);
switch (format) {
case BINARY:
return TypeFactory.defaultInstance().constructType(ChoiceAnswer.class);
case CHOICE:
return TypeFactory.defaultInstance().constructType(ChoiceAnswer.class);
case NUMBER:
return TypeFactory.defaultInstance().constructType(ChoiceAnswer.class);
case SCALE:
return TypeFactory.defaultInstance().constructType(ChoiceAnswer.class);
case TEXT:
return TypeFactory.defaultInstance().constructType(TextAnswer.class);
default:
throw new IllegalArgumentException("Unsupported type ID.");
}
}
@Override
public JsonTypeInfo.Id getMechanism() {
return JsonTypeInfo.Id.CUSTOM;
}
}
package de.thm.arsnova.entities.serialization;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.DatabindContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
import com.fasterxml.jackson.databind.type.TypeFactory;
import de.thm.arsnova.entities.ChoiceQuestionContent;
import de.thm.arsnova.entities.Content;
import java.io.IOException;
public class FormatContentTypeIdResolver extends TypeIdResolverBase {
@Override
public String idFromValue(final Object value) {
if (value instanceof Content) {
return ((Content) value).getFormat().toString();
} else {
throw new IllegalArgumentException("Unsupported type.");
}
}
@Override
public String idFromValueAndType(final Object value, final Class<?> suggestedType) {
return idFromValue(value);
}
@Override
public JavaType typeFromId(final DatabindContext context, final String id) throws IOException {
Content.Format format = Content.Format.valueOf(id);
switch (format) {
case BINARY:
return TypeFactory.defaultInstance().constructType(ChoiceQuestionContent.class);
case CHOICE:
return TypeFactory.defaultInstance().constructType(ChoiceQuestionContent.class);
case NUMBER:
return TypeFactory.defaultInstance().constructType(ChoiceQuestionContent.class);
case SCALE:
return TypeFactory.defaultInstance().constructType(ChoiceQuestionContent.class);
case TEXT:
return TypeFactory.defaultInstance().constructType(Content.class);
default:
throw new IllegalArgumentException("Unsupported type ID.");
}
}
@Override
public JsonTypeInfo.Id getMechanism() {
return JsonTypeInfo.Id.CUSTOM;
}
}
...@@ -4,7 +4,7 @@ var designDoc = { ...@@ -4,7 +4,7 @@ var designDoc = {
"views": { "views": {
"by_id": { "by_id": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit(doc._id, {_rev: doc._rev}); emit(doc._id, {_rev: doc._rev});
} }
}, },
...@@ -12,14 +12,14 @@ var designDoc = { ...@@ -12,14 +12,14 @@ var designDoc = {
}, },
"by_contentid": { "by_contentid": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit(doc.contentId, {_rev: doc._rev}); emit(doc.contentId, {_rev: doc._rev});
} }
} }
}, },
"by_contentid_round_body_subject": { "by_contentid_round_body_subject": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit([doc.contentId, doc.round, doc.abstention, doc.body, doc.subject, doc.successfulFreeTextAnswer], {_rev: doc._rev}); emit([doc.contentId, doc.round, doc.abstention, doc.body, doc.subject, doc.successfulFreeTextAnswer], {_rev: doc._rev});
} }
}, },
...@@ -27,7 +27,7 @@ var designDoc = { ...@@ -27,7 +27,7 @@ var designDoc = {
}, },
"by_contentid_round_selectedchoiceindexes": { "by_contentid_round_selectedchoiceindexes": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit([doc.contentId, doc.round, doc.selectedChoiceIndexes], {_rev: doc._rev}); emit([doc.contentId, doc.round, doc.selectedChoiceIndexes], {_rev: doc._rev});
} }
}, },
...@@ -35,21 +35,21 @@ var designDoc = { ...@@ -35,21 +35,21 @@ var designDoc = {
}, },
"by_contentid_creationtimestamp": { "by_contentid_creationtimestamp": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit([doc.contentId, doc.creationTimestamp], {_rev: doc._rev}); emit([doc.contentId, doc.creationTimestamp], {_rev: doc._rev});
} }
} }
}, },
"by_contentid_creatorid_round": { "by_contentid_creatorid_round": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit([doc.contentId, doc.creatorId, doc.round], {_rev: doc._rev}); emit([doc.contentId, doc.creatorId, doc.round], {_rev: doc._rev});
} }
} }
}, },
"by_roomid": { "by_roomid": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit(doc.roomId, {_rev: doc._rev}); emit(doc.roomId, {_rev: doc._rev});
} }
}, },
...@@ -57,7 +57,7 @@ var designDoc = { ...@@ -57,7 +57,7 @@ var designDoc = {
}, },
"by_roomid_variant": { "by_roomid_variant": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit([doc.roomId, doc.questionVariant], {_rev: doc._rev}); emit([doc.roomId, doc.questionVariant], {_rev: doc._rev});
} }
}, },
...@@ -65,21 +65,21 @@ var designDoc = { ...@@ -65,21 +65,21 @@ var designDoc = {
}, },
"by_creatorid_roomid": { "by_creatorid_roomid": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit([doc.creatorId, doc.roomId], {_rev: doc._rev}); emit([doc.creatorId, doc.roomId], {_rev: doc._rev});
} }
} }
}, },
"contentid_by_creatorid_roomid_variant": { "contentid_by_creatorid_roomid_variant": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit([doc.user, doc.roomId, doc.questionVariant], doc.contentId); emit([doc.user, doc.roomId, doc.questionVariant], doc.contentId);
} }
} }
}, },
"contentid_round_by_creatorid_roomid_variant": { "contentid_round_by_creatorid_roomid_variant": {
"map": function (doc) { "map": function (doc) {
if (["Answer", "ChoiceAnswer", "TextAnswer"].indexOf(doc.type) !== -1) { if (doc.type === "Answer") {
emit([doc.creatorId, doc.roomId, doc.questionVariant], [doc.contentId, doc.round]); emit([doc.creatorId, doc.roomId, doc.questionVariant], [doc.contentId, doc.round]);
} }
} }
......
...@@ -4,7 +4,7 @@ var designDoc = { ...@@ -4,7 +4,7 @@ var designDoc = {
"views": { "views": {
"by_id": { "by_id": {
"map": function (doc) { "map": function (doc) {
if (["Content", "ChoiceQuestionContent"].indexOf(doc.type) !== -1) { if (doc.type === "Content") {
emit(doc._id, {_rev: doc._rev}); emit(doc._id, {_rev: doc._rev});
} }
}, },
...@@ -12,7 +12,7 @@ var designDoc = { ...@@ -12,7 +12,7 @@ var designDoc = {
}, },
"by_roomid": { "by_roomid": {
"map": function (doc) { "map": function (doc) {
if (["Content", "ChoiceQuestionContent"].indexOf(doc.type) !== -1) { if (doc.type === "Content") {
emit(doc.roomId, {_rev: doc._rev}); emit(doc.roomId, {_rev: doc._rev});
} }
}, },
...@@ -20,7 +20,7 @@ var designDoc = { ...@@ -20,7 +20,7 @@ var designDoc = {
}, },
"by_roomid_group_locked": { "by_roomid_group_locked": {
"map": function (doc) { "map": function (doc) {
if (["Content", "ChoiceQuestionContent"].indexOf(doc.type) !== -1) { if (doc.type === "Content") {
emit([doc.roomId, doc.group, doc.locked, doc.subject, doc.body.substr(0, 16)], {_rev: doc._rev}); emit([doc.roomId, doc.group, doc.locked, doc.subject, doc.body.substr(0, 16)], {_rev: doc._rev});
} }
}, },
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment