From 130793de619447de4c32bff263a0c8703036847e Mon Sep 17 00:00:00 2001 From: srishti Date: Wed, 9 Aug 2023 18:57:47 +0200 Subject: [PATCH] EA-3236 add other functionality like datsource, repository, controller and application. Also added interfaces --- pom.xml | 11 +- record-api-definitions/pom.xml | 1 + .../api/record/datatypes/Literal.java | 2 + .../eu/europeana/api/record/model/Agent.java | 6 + .../api/record/model/Aggregation.java | 22 +++ .../europeana/api/record/model/EdmEntity.java | 8 + .../eu/europeana/api/record/model/Entity.java | 16 ++ .../record/model/EuropeanaAggregation.java | 10 + .../api/record/model/ProvidedCHO.java | 8 + .../eu/europeana/api/record/model/Proxy.java | 52 ++++++ .../api/record/model/TechMetadata.java | 8 + .../api/record/model/WebResource.java | 14 ++ record-api-impl/pom.xml | 29 +++ .../java/eu/europeana/api/record/Record.java | 99 ++++++++++ .../api/record/codec/LiteralCodec.java | 36 ++++ .../api/record/codec/LiteralMapCodec.java | 57 ++++++ .../eu/europeana/api/record/impl/Agent.java | 9 - .../europeana/api/record/impl/AgentImpl.java | 21 +++ .../api/record/impl/Aggregation.java | 38 ---- .../api/record/impl/AggregationImpl.java | 65 +++++++ .../europeana/api/record/impl/EdmEntity.java | 14 -- .../api/record/impl/EdmEntityImpl.java | 30 +++ .../eu/europeana/api/record/impl/Entity.java | 12 -- .../europeana/api/record/impl/EntityImpl.java | 48 +++++ .../api/record/impl/EuropeanaAggregation.java | 12 -- .../record/impl/EuropeanaAggregationImpl.java | 26 +++ .../api/record/impl/LiteralImpl.java | 19 ++ .../api/record/impl/ProvidedCHO.java | 24 --- .../api/record/impl/ProvidedCHOImpl.java | 30 +++ .../eu/europeana/api/record/impl/Proxy.java | 105 ----------- .../europeana/api/record/impl/ProxyImpl.java | 176 ++++++++++++++++++ .../eu/europeana/api/record/impl/Record.java | 13 -- .../api/record/impl/TechMetadata.java | 6 - .../api/record/impl/TechMetadataImpl.java | 25 +++ .../api/record/impl/WebResource.java | 16 -- .../api/record/impl/WebResourceImpl.java | 42 +++++ .../serialization/LiteralMapConverter.java | 32 ++++ .../serialization/LiteralStringConverter.java | 18 ++ .../record/vocabulary/AppConfigConstants.java | 12 ++ .../api/record/vocabulary/RecordFields.java | 14 ++ record-api-mongo/pom.xml | 80 ++++++++ .../api/record/config/DataSourceConfig.java | 88 +++++++++ .../record/repository/AbstractRepository.java | 17 ++ .../record/repository/RecordRepository.java | 72 +++++++ record-api-web/pom.xml | 136 ++++++++++++++ .../eu/europeana/api/record/RecordApp.java | 40 ++++ .../api/record/config/AppConfig.java | 35 ++++ .../record/config/RecordApiConfiguration.java | 54 ++++++ .../api/record/service/RecordService.java | 27 +++ .../api/record/web/RecordController.java | 45 +++++ .../src/main/resources/record-api.properties | 12 ++ 51 files changed, 1541 insertions(+), 251 deletions(-) create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/Agent.java create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/Aggregation.java create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/EdmEntity.java create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/Entity.java create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/EuropeanaAggregation.java create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/ProvidedCHO.java create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/Proxy.java create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/TechMetadata.java create mode 100644 record-api-definitions/src/main/java/eu/europeana/api/record/model/WebResource.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/Record.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/codec/LiteralCodec.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/codec/LiteralMapCodec.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/Agent.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/AgentImpl.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/Aggregation.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/AggregationImpl.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/EdmEntity.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/EdmEntityImpl.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/Entity.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/EntityImpl.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/EuropeanaAggregation.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/EuropeanaAggregationImpl.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/LiteralImpl.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/ProvidedCHO.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/ProvidedCHOImpl.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/Proxy.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/ProxyImpl.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/Record.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/TechMetadata.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/TechMetadataImpl.java delete mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/WebResource.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/impl/WebResourceImpl.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/serialization/LiteralMapConverter.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/serialization/LiteralStringConverter.java create mode 100644 record-api-impl/src/main/java/eu/europeana/api/record/vocabulary/AppConfigConstants.java create mode 100644 record-api-mongo/pom.xml create mode 100644 record-api-mongo/src/main/java/eu/europeana/api/record/config/DataSourceConfig.java create mode 100644 record-api-mongo/src/main/java/eu/europeana/api/record/repository/AbstractRepository.java create mode 100644 record-api-mongo/src/main/java/eu/europeana/api/record/repository/RecordRepository.java create mode 100644 record-api-web/pom.xml create mode 100644 record-api-web/src/main/java/eu/europeana/api/record/RecordApp.java create mode 100644 record-api-web/src/main/java/eu/europeana/api/record/config/AppConfig.java create mode 100644 record-api-web/src/main/java/eu/europeana/api/record/config/RecordApiConfiguration.java create mode 100644 record-api-web/src/main/java/eu/europeana/api/record/service/RecordService.java create mode 100644 record-api-web/src/main/java/eu/europeana/api/record/web/RecordController.java create mode 100644 record-api-web/src/main/resources/record-api.properties diff --git a/pom.xml b/pom.xml index 05ce1d2..c5c30d9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,6 +4,8 @@ record-api-definitions record-api-impl + record-api-mongo + record-api-web @@ -52,11 +54,15 @@ **/model/**/* 0.3.21 - 2.11.4 + 2.15.2 + 3.1.2 + 6.0.11 + 3.1.2 3.0.0 - 2.1.4 + + 2.3.7 3.1 5.0.0 3.0.0-M5 @@ -64,6 +70,7 @@ 3.21.0 4.7.3.5 3.7.0.1746 + 3.13.0 diff --git a/record-api-definitions/pom.xml b/record-api-definitions/pom.xml index c2447fd..3e69789 100644 --- a/record-api-definitions/pom.xml +++ b/record-api-definitions/pom.xml @@ -16,4 +16,5 @@ ${java.version} + \ No newline at end of file diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/datatypes/Literal.java b/record-api-definitions/src/main/java/eu/europeana/api/record/datatypes/Literal.java index 2fedd7c..9d2a81e 100644 --- a/record-api-definitions/src/main/java/eu/europeana/api/record/datatypes/Literal.java +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/datatypes/Literal.java @@ -3,4 +3,6 @@ public interface Literal { T getValue(); + + void setValue(T value); } diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/Agent.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/Agent.java new file mode 100644 index 0000000..7c6b6b6 --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/Agent.java @@ -0,0 +1,6 @@ +package eu.europeana.api.record.model; + +public interface Agent { + + String getType(); +} diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/Aggregation.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/Aggregation.java new file mode 100644 index 0000000..5ee8443 --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/Aggregation.java @@ -0,0 +1,22 @@ +package eu.europeana.api.record.model; + +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.datatypes.ObjectReference; + +import java.util.List; + +public interface Aggregation { + + Literal getType(); + + Literal getIsShownBy(); + + List getHasViews(); + + void setType(Literal type); + + void setIsShownBy(Literal isShownBy); + + void setHasViews(List hasViews); + +} diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/EdmEntity.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/EdmEntity.java new file mode 100644 index 0000000..fb16121 --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/EdmEntity.java @@ -0,0 +1,8 @@ +package eu.europeana.api.record.model; + +public interface EdmEntity { + + String getAbout(); + + void setAbout(String about); +} diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/Entity.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/Entity.java new file mode 100644 index 0000000..cdcb50b --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/Entity.java @@ -0,0 +1,16 @@ +package eu.europeana.api.record.model; + +import eu.europeana.api.record.datatypes.Literal; + +import java.util.Map; + +public interface Entity { + + String getAbout(); + + void setAbout(String about); + + Literal getPrefLabel(String language); + + void setPrefLabel(Map> prefLabel); +} diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/EuropeanaAggregation.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/EuropeanaAggregation.java new file mode 100644 index 0000000..8c439dd --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/EuropeanaAggregation.java @@ -0,0 +1,10 @@ +package eu.europeana.api.record.model; + +import eu.europeana.api.record.datatypes.Literal; + +public interface EuropeanaAggregation { + + Literal getType(); + + void setType(Literal type); +} diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/ProvidedCHO.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/ProvidedCHO.java new file mode 100644 index 0000000..282041e --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/ProvidedCHO.java @@ -0,0 +1,8 @@ +package eu.europeana.api.record.model; + +public interface ProvidedCHO { + + String getType(); + + void setType(String type); +} diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/Proxy.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/Proxy.java new file mode 100644 index 0000000..3f60e04 --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/Proxy.java @@ -0,0 +1,52 @@ +package eu.europeana.api.record.model; + +import eu.europeana.api.record.datatypes.Literal; + +import java.util.List; +import java.util.Map; + +public interface Proxy { + + Literal getType(); + + EuropeanaAggregation getProxyIn(); + + Literal getProxyFor(); + + Literal getTitle(String language); + + Literal getCreator(String language); + + Literal getAlternative(String language); + + Literal getDescription(String language); + + Literal getIdentifier(String language); + + List> getTitles(); + + List> getAlternatives(); + + List> getCreators(); + + List> getIdentifiers(); + + List> getDescriptions(); + + void setType(Literal type); + + void setTitle(Map>> title); + + void setAlternative(Map>> alternative); + + void setDescription(Map>> description); + + void setCreator(Map>> creator); + + void setIdentifier(Map>> identifier); + + void setProxyIn(EuropeanaAggregation proxyIn); + + void setProxyFor(Literal proxyFor); + +} diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/TechMetadata.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/TechMetadata.java new file mode 100644 index 0000000..7eb98ac --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/TechMetadata.java @@ -0,0 +1,8 @@ +package eu.europeana.api.record.model; + +public interface TechMetadata { + + Long getFileByteSize(); + + void setFileByteSize(Long fileByteSize); +} diff --git a/record-api-definitions/src/main/java/eu/europeana/api/record/model/WebResource.java b/record-api-definitions/src/main/java/eu/europeana/api/record/model/WebResource.java new file mode 100644 index 0000000..b99f03c --- /dev/null +++ b/record-api-definitions/src/main/java/eu/europeana/api/record/model/WebResource.java @@ -0,0 +1,14 @@ +package eu.europeana.api.record.model; + +import eu.europeana.api.record.datatypes.Literal; + +public interface WebResource { + + Literal getType(); + + void setType(Literal type); + + TechMetadata getTechMetadata(); + + void setTechMetadata(TechMetadata techMetadata); +} diff --git a/record-api-impl/pom.xml b/record-api-impl/pom.xml index 5d04218..d0e1fa9 100644 --- a/record-api-impl/pom.xml +++ b/record-api-impl/pom.xml @@ -22,6 +22,35 @@ record-api-definitions 1.0-SNAPSHOT + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + + + dev.morphia.morphia + morphia-core + ${morphia.version} + + + + + org.springframework.data + spring-data-mongodb + 4.1.2 + + + \ No newline at end of file diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/Record.java b/record-api-impl/src/main/java/eu/europeana/api/record/Record.java new file mode 100644 index 0000000..8a016c8 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/Record.java @@ -0,0 +1,99 @@ +package eu.europeana.api.record; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Id; +import eu.europeana.api.record.impl.*; +import eu.europeana.api.record.model.*; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +import static eu.europeana.api.record.vocabulary.RecordFields.*; + +@Entity +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(value = JsonInclude.Include.NON_EMPTY) +// TODO add custom validators later once we know field validations +public class Record { + + @Id + private String id; + +// @JsonDeserialize(as = ProvidedCHOImpl.class) +// private ProvidedCHO providedCHO; + + @JsonDeserialize(contentAs = ProxyImpl.class) + private List proxies; + + @JsonDeserialize(as = AggregationImpl.class) + private Aggregation aggregation; + + @JsonDeserialize(contentAs = WebResourceImpl.class) + private List webResources; + + @JsonDeserialize(contentAs = AgentImpl.class) + private List agents; + + protected Record() {} + + + @JsonGetter(CONTEXT) + public String getContext() { + return EDM_CONTEXT; + } + + @JsonGetter(ID) + public String getId() { + return id; + } + + @JsonSetter(ID) + public void setId(String id) { + this.id = id; + } + + // public ProvidedCHO getProvidedCHO() { +// return providedCHO; +// } +// +// public void setProvidedCHO(ProvidedCHO providedCHO) { +// this.providedCHO = providedCHO; +// } + + public List getProxies() { + return proxies; + } + + public void setProxies(List proxies) { + this.proxies = proxies; + } + + public Aggregation getAggregation() { + return aggregation; + } + + public void setAggregation(Aggregation aggregation) { + this.aggregation = aggregation; + } + + public List getWebResources() { + return webResources; + } + + public void setWebResources(List webResources) { + this.webResources = webResources; + } + + public List getAgents() { + return agents; + } + + public void setAgents(List agents) { + this.agents = agents; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/codec/LiteralCodec.java b/record-api-impl/src/main/java/eu/europeana/api/record/codec/LiteralCodec.java new file mode 100644 index 0000000..514e241 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/codec/LiteralCodec.java @@ -0,0 +1,36 @@ +package eu.europeana.api.record.codec; + +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.impl.LiteralImpl; +import org.bson.BsonReader; +import org.bson.BsonWriter; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; + +public class LiteralCodec implements Codec { + +// @Override +// public void encode(final BsonWriter writer, final Literal value, final EncoderContext encoderContext) { +// writer.writeString(value.getValue()); +// } + + @Override + public void encode(BsonWriter bsonWriter, Literal literal, EncoderContext encoderContext) { + bsonWriter.writeString(String.valueOf(literal.getValue())); + + } + + @Override + public Class getEncoderClass() { + return Literal.class; + } + + @Override + public Literal decode(final BsonReader reader, final DecoderContext decoderContext) { + Literal literal = new LiteralImpl<>(); + literal.setValue(reader.readString()); + return literal; + } + +} \ No newline at end of file diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/codec/LiteralMapCodec.java b/record-api-impl/src/main/java/eu/europeana/api/record/codec/LiteralMapCodec.java new file mode 100644 index 0000000..fc7ddcd --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/codec/LiteralMapCodec.java @@ -0,0 +1,57 @@ +package eu.europeana.api.record.codec; + +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.impl.LiteralImpl; +import org.bson.BsonReader; +import org.bson.BsonWriter; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class LiteralMapCodec implements Codec >>> { + +// @Override +// public void encode(final BsonWriter writer, final Literal value, final EncoderContext encoderContext) { +// writer.writeString(value.getValue()); +// } +// +// @Override +// public void encode(BsonWriter bsonWriter, Literal literal, EncoderContext encoderContext) { +// bsonWriter.write(String.valueOf(literal.getValue())); +// +// } + + @Override + public void encode(BsonWriter bsonWriter, Map>> stringLiteralMap, EncoderContext encoderContext) { + + for (Map.Entry>> entry : stringLiteralMap.entrySet()) { + System.out.println(entry.getKey() + "/" + entry.getValue()); + bsonWriter.writeStartArray(entry.getKey()); + entry.getValue().stream().forEach(value -> { + bsonWriter.writeString(value.getValue()); + }); + bsonWriter.writeEndArray(); + + } + + + } + + @Override + public Class>>> getEncoderClass() { + Map>> map = new HashMap<>(); + return (Class>>>) map.getClass(); + } + + @Override + public Map>> decode(final BsonReader reader, final DecoderContext decoderContext) { + Map>> resultMap = new HashMap<>(); + // TODO yet to implment + return resultMap; + } + +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Agent.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/Agent.java deleted file mode 100644 index bb4d5c0..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Agent.java +++ /dev/null @@ -1,9 +0,0 @@ -package eu.europeana.api.record.impl; - -import eu.europeana.api.record.vocabulary.EntityTypes; - -public class Agent extends Entity { - - private String type = EntityTypes.Agent.getEntityType(); - -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/AgentImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/AgentImpl.java new file mode 100644 index 0000000..e125ba8 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/AgentImpl.java @@ -0,0 +1,21 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import eu.europeana.api.record.model.Agent; +import eu.europeana.api.record.vocabulary.EntityTypes; + +@JsonInclude(value = JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class AgentImpl extends EntityImpl implements Agent { + + private String type = EntityTypes.Agent.getEntityType(); + + public AgentImpl() { + } + + @Override + public String getType() { + return type; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Aggregation.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/Aggregation.java deleted file mode 100644 index 68aab2e..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Aggregation.java +++ /dev/null @@ -1,38 +0,0 @@ -package eu.europeana.api.record.impl; - -import eu.europeana.api.record.datatypes.Literal; -import eu.europeana.api.record.datatypes.ObjectReference; - -import java.util.List; - -// TODO make inteface -public class Aggregation extends EdmEntity { - - private Literal type; - private Literal isShownBy; - private List hasViews; // multiple object refre - - public Literal getType() { - return type; - } - - public void setType(Literal type) { - this.type = type; - } - - public Literal getIsShownBy() { - return isShownBy; - } - - public void setIsShownBy(Literal isShownBy) { - this.isShownBy = isShownBy; - } - - public List getHasViews() { - return hasViews; - } - - public void setHasViews(List hasViews) { - this.hasViews = hasViews; - } -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/AggregationImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/AggregationImpl.java new file mode 100644 index 0000000..2ffc97a --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/AggregationImpl.java @@ -0,0 +1,65 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import dev.morphia.annotations.Entity; +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.datatypes.ObjectReference; +import eu.europeana.api.record.model.Aggregation; +import eu.europeana.api.record.serialization.LiteralStringConverter; + +import java.util.List; + +@JsonInclude(value = JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class AggregationImpl extends EdmEntityImpl implements Aggregation { + + @JsonDeserialize(converter = LiteralStringConverter.class) + private Literal type; + + @JsonDeserialize(converter = LiteralStringConverter.class) + private Literal isShownBy; + + /** + * Multiple object reference. + * For now, we can deserialize as List> + * As has Views only contains strings and + * not the referenced object yet when registering a record. + */ + @JsonDeserialize(converter = LiteralStringConverter.class) + private List hasViews; + + + public AggregationImpl() { + } + + @Override + public Literal getType() { + return type; + } + + @Override + public Literal getIsShownBy() { + return isShownBy; + } + + @Override + public List getHasViews() { + return hasViews; + } + + @Override + public void setType(Literal type) { + this.type = type; + } + + @Override + public void setIsShownBy(Literal isShownBy) { + this.isShownBy = isShownBy; + } + + @Override + public void setHasViews(List hasViews) { + this.hasViews = hasViews; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/EdmEntity.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/EdmEntity.java deleted file mode 100644 index 4587a3a..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/EdmEntity.java +++ /dev/null @@ -1,14 +0,0 @@ -package eu.europeana.api.record.impl; - -public class EdmEntity { - - private String about; - - public String getAbout() { - return about; - } - - public void setAbout(String about) { - this.about = about; - } -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/EdmEntityImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/EdmEntityImpl.java new file mode 100644 index 0000000..89020d4 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/EdmEntityImpl.java @@ -0,0 +1,30 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonSetter; +import dev.morphia.annotations.Id; +import eu.europeana.api.record.model.EdmEntity; + +import static eu.europeana.api.record.vocabulary.RecordFields.ID; + +@JsonInclude(value = JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public abstract class EdmEntityImpl implements EdmEntity { + + @Id + private String about; + + @Override + @JsonGetter(ID) + public String getAbout() { + return about; + } + + @Override + @JsonSetter(ID) + public void setAbout(String about) { + this.about = about; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Entity.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/Entity.java deleted file mode 100644 index 1bc1200..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Entity.java +++ /dev/null @@ -1,12 +0,0 @@ -package eu.europeana.api.record.impl; - -import eu.europeana.api.record.datatypes.Literal; - -import java.util.Map; - -public abstract class Entity { - - // ID of entity - protected String about; - protected Map, Literal> prefLabel; -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/EntityImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/EntityImpl.java new file mode 100644 index 0000000..7058b32 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/EntityImpl.java @@ -0,0 +1,48 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.model.Entity; +import eu.europeana.api.record.serialization.LiteralMapConverter; + +import static eu.europeana.api.record.vocabulary.RecordFields.ID; + +import java.util.Map; + +@JsonInclude(value = JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public abstract class EntityImpl implements Entity { + + // ID of entity + protected String about; + + @JsonDeserialize(converter = LiteralMapConverter.class) + protected Map> prefLabel; + + @Override + @JsonGetter(ID) + public String getAbout() { + return about; + } + + @Override + @JsonSetter(ID) + public void setAbout(String about) { + this.about = about; + } + + public Map> getPrefLabel() { + return prefLabel; + } + + @Override + public Literal getPrefLabel(String language) { + return prefLabel.get(language); + } + + @Override + public void setPrefLabel(Map> prefLabel) { + this.prefLabel = prefLabel; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/EuropeanaAggregation.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/EuropeanaAggregation.java deleted file mode 100644 index ab3cc62..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/EuropeanaAggregation.java +++ /dev/null @@ -1,12 +0,0 @@ -package eu.europeana.api.record.impl; - -import eu.europeana.api.record.datatypes.Literal; - -public class EuropeanaAggregation extends EdmEntity { - - private Literal type; - - public Literal getType() { - return type; - } -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/EuropeanaAggregationImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/EuropeanaAggregationImpl.java new file mode 100644 index 0000000..c7174cd --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/EuropeanaAggregationImpl.java @@ -0,0 +1,26 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.model.EuropeanaAggregation; +import eu.europeana.api.record.serialization.LiteralStringConverter; + +public class EuropeanaAggregationImpl extends EdmEntityImpl implements EuropeanaAggregation { + + @JsonDeserialize(converter = LiteralStringConverter.class) + private Literal type; + + public EuropeanaAggregationImpl() { + } + + @Override + public Literal getType() { + return type; + } + + @Override + public void setType(Literal type) { + this.type = type; + } + +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/LiteralImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/LiteralImpl.java new file mode 100644 index 0000000..04aebe1 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/LiteralImpl.java @@ -0,0 +1,19 @@ +package eu.europeana.api.record.impl; + +public class LiteralImpl implements eu.europeana.api.record.datatypes.Literal { + + private T value; + + public LiteralImpl() { + } + + @Override + public T getValue() { + return value; + } + + @Override + public void setValue(T value) { + this.value = value; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProvidedCHO.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProvidedCHO.java deleted file mode 100644 index 8c468b9..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProvidedCHO.java +++ /dev/null @@ -1,24 +0,0 @@ -package eu.europeana.api.record.impl; - -public class ProvidedCHO extends EdmEntity { - - private String type; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - @Override - public String getAbout() { - return super.getAbout(); - } - - @Override - public void setAbout(String about) { - super.setAbout(about); - } -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProvidedCHOImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProvidedCHOImpl.java new file mode 100644 index 0000000..cb38c18 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProvidedCHOImpl.java @@ -0,0 +1,30 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.annotation.*; +import dev.morphia.annotations.Embedded; +import dev.morphia.annotations.Entity; +import eu.europeana.api.record.model.ProvidedCHO; +import eu.europeana.api.record.vocabulary.EntityTypes; + +import static eu.europeana.api.record.vocabulary.RecordFields.TYPE; + +@JsonInclude(value = JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ProvidedCHOImpl extends EdmEntityImpl implements ProvidedCHO { + + private String type = EntityTypes.Agent.getEntityType(); + + public ProvidedCHOImpl() {} + + @Override + @JsonGetter(TYPE) + public String getType() { + return type; + } + + @Override + @JsonSetter(TYPE) + public void setType(String type) { + this.type = type; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Proxy.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/Proxy.java deleted file mode 100644 index a526148..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Proxy.java +++ /dev/null @@ -1,105 +0,0 @@ -package eu.europeana.api.record.impl; - -import eu.europeana.api.record.datatypes.Literal; - -import java.util.List; -import java.util.Map; - -public class Proxy extends EdmEntity { - - // TODO for def -> @none there are multiple values present - private Literal type; - private Map, List>> title; - - // todo - private Map, List>> alternative; - private Map, List>> description; - private Map, List>> creator; - private Map, List>> identifier; - private List> proxyIn; - private Literal proxyFor; - - public Literal getType() { - return type; - } - - public void setType(Literal type) { - this.type = type; - } - - public Literal getTitle(String language) { - return title.get(language).get(0); - } - - public void setTitle(Map,List>> title) { - this.title = title; - } - - public Literal getAlternative(String language) { - return alternative.get(language).get(0); - } - - public void setAlternative(Map, List>> alternative) { - this.alternative = alternative; - } - - public Literal getDescription(String language) { - return description.get(language).get(0); - } - - public void setDescription(Map, List>> description) { - this.description = description; - } - - public Literal getCreator(String language) { - return creator.get(language).get(0); - } - - public void setCreator(Map, List>> creator) { - this.creator = creator; - } - - public Literal getIdentifier(String language) { - return identifier.get(language).get(0); - } - - public void setIdentifier(Map, List>> identifier) { - this.identifier = identifier; - } - - public List> getProxyIn() { - return proxyIn; - } - - public void setProxyIn(List> proxyIn) { - this.proxyIn = proxyIn; - } - - public Literal getProxyFor() { - return proxyFor; - } - - public void setProxyFor(Literal proxyFor) { - this.proxyFor = proxyFor; - } - - // this is for @none - public List> getTitles() { - return title.get("@none"); - } - - public List> getAlternatives() { - return alternative.get("@none"); - } - - public List> getCreators() { - return creator.get("@none"); - } - - public List> getIdentifiers() { - return identifier.get("@none"); - } - - - -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProxyImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProxyImpl.java new file mode 100644 index 0000000..0a44fa9 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/ProxyImpl.java @@ -0,0 +1,176 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import dev.morphia.annotations.Entity; +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.model.EuropeanaAggregation; +import eu.europeana.api.record.model.Proxy; +import eu.europeana.api.record.serialization.LiteralStringConverter; +import eu.europeana.api.record.serialization.LiteralMapConverter; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.mapping.FieldType; + +import java.util.List; +import java.util.Map; + +@Entity +public class ProxyImpl extends EdmEntityImpl implements Proxy { + +// @Field(targetType = FieldType.STRING) + @JsonDeserialize(converter = LiteralStringConverter.class) + private Literal type; + +// @Field(targetType = FieldType.ARRAY) + @JsonDeserialize(converter = LiteralMapConverter.class) + private Map>> title; + + @JsonDeserialize(converter = LiteralMapConverter.class) + private Map>> alternative; + + @JsonDeserialize(converter = LiteralMapConverter.class) + private Map>> description; + + @JsonDeserialize(converter = LiteralMapConverter.class) + private Map>> creator; + + @JsonDeserialize(converter = LiteralMapConverter.class) + private Map>> identifier; + + @JsonDeserialize(as = EuropeanaAggregationImpl.class) + private EuropeanaAggregation proxyIn; + + @JsonDeserialize(converter = LiteralStringConverter.class) + private Literal proxyFor; + + public ProxyImpl() { + } + + @Override + public Literal getType() { + return type; + } + + @Override + public void setType(Literal type) { + this.type = type; + } + + public Map>> getTitle() { + return title; + } + + @Override + public void setTitle(Map>> title) { + this.title = title; + } + + public Map>> getAlternative() { + return alternative; + } + + @Override + public void setAlternative(Map>> alternative) { + this.alternative = alternative; + } + + public Map>> getDescription() { + return description; + } + + @Override + public void setDescription(Map>> description) { + this.description = description; + } + + public Map>> getCreator() { + return creator; + } + + @Override + public void setCreator(Map>> creator) { + this.creator = creator; + } + + public Map>> getIdentifier() { + return identifier; + } + + @Override + public void setIdentifier(Map>> identifier) { + this.identifier = identifier; + } + + @Override + public EuropeanaAggregation getProxyIn() { + return proxyIn; + } + + public void setProxyIn(EuropeanaAggregation proxyIn) { + this.proxyIn = proxyIn; + } + + @Override + public Literal getProxyFor() { + return proxyFor; + } + + @Override + public void setProxyFor(Literal proxyFor) { + this.proxyFor = proxyFor; + } + + // Getters to fetch the language value + + @Override + public Literal getTitle(String language) { + return title.get(language).get(0); + } + + @Override + public Literal getCreator(String language) { + return creator.get(language).get(0); + } + + @Override + public Literal getAlternative(String language) { + return alternative.get(language).get(0); + } + + @Override + public Literal getDescription(String language) { + return description.get(language).get(0); + } + + @Override + public Literal getIdentifier(String language) { + return identifier.get(language).get(0); + } + + + // Getters to fetch the non language @none values + + @Override + public List> getTitles() { + return title.get("@none"); + } + + @Override + public List> getAlternatives() { + return alternative.get("@none"); + } + + @Override + public List> getCreators() { + return creator.get("@none"); + } + + @Override + public List> getDescriptions() { + return description.get("@none"); + } + + @Override + public List> getIdentifiers() { + return identifier.get("@none"); + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Record.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/Record.java deleted file mode 100644 index f71a320..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/Record.java +++ /dev/null @@ -1,13 +0,0 @@ -package eu.europeana.api.record.impl; - -public class Record { - - private ProvidedCHO providedCHO; - private Proxy proxy; - private Aggregation aggregation; - private EuropeanaAggregation europeanaAggregation; - private WebResource webResource; - private TechMetadata techMetadata; - private Agent agent; - -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/TechMetadata.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/TechMetadata.java deleted file mode 100644 index f8a5aef..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/TechMetadata.java +++ /dev/null @@ -1,6 +0,0 @@ -package eu.europeana.api.record.impl; - -public class TechMetadata { - - private Long fileByteSize; -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/TechMetadataImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/TechMetadataImpl.java new file mode 100644 index 0000000..9886489 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/TechMetadataImpl.java @@ -0,0 +1,25 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonSetter; +import eu.europeana.api.record.model.TechMetadata; + +public class TechMetadataImpl implements TechMetadata { + + private Long fileByteSize; + + public TechMetadataImpl() { + } + + @Override + @JsonGetter("fileSize") + public Long getFileByteSize() { + return fileByteSize; + } + + @Override + @JsonSetter("fileSize") + public void setFileByteSize(Long fileByteSize) { + this.fileByteSize = fileByteSize; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/WebResource.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/WebResource.java deleted file mode 100644 index 80b3ff7..0000000 --- a/record-api-impl/src/main/java/eu/europeana/api/record/impl/WebResource.java +++ /dev/null @@ -1,16 +0,0 @@ -package eu.europeana.api.record.impl; - -import eu.europeana.api.record.datatypes.Literal; - -public class WebResource extends EdmEntity { - - private Literal type; - - public Literal getType() { - return type; - } - - public void setType(Literal type) { - this.type = type; - } -} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/impl/WebResourceImpl.java b/record-api-impl/src/main/java/eu/europeana/api/record/impl/WebResourceImpl.java new file mode 100644 index 0000000..9fc48db --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/impl/WebResourceImpl.java @@ -0,0 +1,42 @@ +package eu.europeana.api.record.impl; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.model.TechMetadata; +import eu.europeana.api.record.model.WebResource; +import eu.europeana.api.record.serialization.LiteralStringConverter; + +public class WebResourceImpl extends EdmEntityImpl implements WebResource { + + @JsonDeserialize(converter = LiteralStringConverter.class) + private Literal type; + + @JsonDeserialize(as = TechMetadataImpl.class) + private TechMetadata techMetadata; + + public WebResourceImpl() { + } + + @Override + public Literal getType() { + return type; + } + + public void setType(Literal type) { + this.type = type; + } + + public String getAbout() { + return super.getAbout(); + } + + @Override + public TechMetadata getTechMetadata() { + return techMetadata; + } + + @Override + public void setTechMetadata(TechMetadata techMetadata) { + this.techMetadata = techMetadata; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/serialization/LiteralMapConverter.java b/record-api-impl/src/main/java/eu/europeana/api/record/serialization/LiteralMapConverter.java new file mode 100644 index 0000000..fb0d589 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/serialization/LiteralMapConverter.java @@ -0,0 +1,32 @@ +package eu.europeana.api.record.serialization; + +import com.fasterxml.jackson.databind.util.StdConverter; +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.impl.LiteralImpl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Class for converting the Map present in json request to instance Literal Maps + */ +public class LiteralMapConverter extends StdConverter>, Map>>> { + + @Override + public Map>> convert(Map> stringListMap) { + Map>> result = new HashMap<>(); + for (Map.Entry> entry : stringListMap.entrySet()) { + List> values= new ArrayList<>(); + + entry.getValue().stream().forEach(value -> { + Literal literal = new LiteralImpl<>(); + literal.setValue(value); + values.add(literal); + }); + result.put(entry.getKey(), values); + } + return result; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/serialization/LiteralStringConverter.java b/record-api-impl/src/main/java/eu/europeana/api/record/serialization/LiteralStringConverter.java new file mode 100644 index 0000000..c53234e --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/serialization/LiteralStringConverter.java @@ -0,0 +1,18 @@ +package eu.europeana.api.record.serialization; + +import com.fasterxml.jackson.databind.util.StdConverter; +import eu.europeana.api.record.datatypes.Literal; +import eu.europeana.api.record.impl.LiteralImpl; + +/** + * Class for converting the String values present in json request to instance Literal + */ +public class LiteralStringConverter extends StdConverter> { + + @Override + public Literal convert(String s) { + Literal literal = new LiteralImpl<>(); + literal.setValue(s); + return literal; + } +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/vocabulary/AppConfigConstants.java b/record-api-impl/src/main/java/eu/europeana/api/record/vocabulary/AppConfigConstants.java new file mode 100644 index 0000000..dcfd8a3 --- /dev/null +++ b/record-api-impl/src/main/java/eu/europeana/api/record/vocabulary/AppConfigConstants.java @@ -0,0 +1,12 @@ +package eu.europeana.api.record.vocabulary; + +// TODO move it to common package accessible for everything +public class AppConfigConstants { + + public static final String BEAN_RECORD_DATA_STORE = "recordDataStore"; + public static final String BEAN_RECORD_REPO = "recordRepo"; + public static final String BEAN_RECORD_SERVICE = "recordService"; + + + +} diff --git a/record-api-impl/src/main/java/eu/europeana/api/record/vocabulary/RecordFields.java b/record-api-impl/src/main/java/eu/europeana/api/record/vocabulary/RecordFields.java index 99601d4..be62c10 100644 --- a/record-api-impl/src/main/java/eu/europeana/api/record/vocabulary/RecordFields.java +++ b/record-api-impl/src/main/java/eu/europeana/api/record/vocabulary/RecordFields.java @@ -4,4 +4,18 @@ public interface RecordFields { public static final String CONTEXT = "@context"; public static final String EDM_CONTEXT = "http://www.europeana.eu/schemas/context/edm.jsonld"; + + + public static final String ID = "id"; + public static final String TYPE = "type"; + public static final String PREF_LABEL = "prefLabel"; + public static final String IS_SHOWN_BY = "isShownBy"; + public static final String HAS_VIEWS = "hasViews"; + + public static final String PROVIDED_CHO = "providedCHO"; + + public static final String AGGREGATION = "Aggregation"; + public static final String IS_AGGREGATED_BY = "isAggregatedBy"; + + } diff --git a/record-api-mongo/pom.xml b/record-api-mongo/pom.xml new file mode 100644 index 0000000..5209882 --- /dev/null +++ b/record-api-mongo/pom.xml @@ -0,0 +1,80 @@ + + + + record-api + eu.europeana.api + 1.0-SNAPSHOT + + 4.0.0 + + record-api-mongo + + + ${java.version} + ${java.version} + + + + + + + + eu.europeana.api + record-api-impl + 1.0-SNAPSHOT + + + + dev.morphia.morphia + morphia-core + ${morphia.version} + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + org.apache.commons + commons-lang3 + ${apache.commomLang3.version} + + + + org.springframework + spring-context + ${spring-framework.version} + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + ${spring-boot.version} + test + + + ch.qos.logback + logback-classic + + + org.springframework.boot + spring-boot-starter-logging + + + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + + + \ No newline at end of file diff --git a/record-api-mongo/src/main/java/eu/europeana/api/record/config/DataSourceConfig.java b/record-api-mongo/src/main/java/eu/europeana/api/record/config/DataSourceConfig.java new file mode 100644 index 0000000..bae2ac3 --- /dev/null +++ b/record-api-mongo/src/main/java/eu/europeana/api/record/config/DataSourceConfig.java @@ -0,0 +1,88 @@ +package eu.europeana.api.record.config; + +import com.mongodb.Block; +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.connection.ConnectionPoolSettings; +import java.util.concurrent.TimeUnit; +import dev.morphia.Datastore; +import dev.morphia.Morphia; +import dev.morphia.mapping.MapperOptions; +import eu.europeana.api.record.codec.LiteralCodec; +import eu.europeana.api.record.codec.LiteralMapCodec; +import eu.europeana.api.record.vocabulary.AppConfigConstants; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import org.bson.codecs.configuration.CodecRegistry; +import org.bson.codecs.pojo.PojoCodecProvider; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.PropertySource; +import static org.bson.codecs.configuration.CodecRegistries.fromProviders; +import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; +import org.bson.codecs.configuration.CodecRegistries; +import org.bson.codecs.configuration.CodecRegistry; + +@Configuration +@PropertySource( + value = {"classpath:record-api.properties", "classpath:record-api.user.properties"}, + ignoreResourceNotFound = true) +public class DataSourceConfig { + + private static final Logger LOGGER = LogManager.getLogger(DataSourceConfig.class); + + @Value("${mongo.connectionUrl}") + private String hostUri; + + @Value("${mongo.max.idle.time.millisec: 10000}") + private long mongoMaxIdleTimeMillisec; + + @Value("${mongo.record.database}") + private String recordDatabase; + + + @Bean + public MongoClient mongoClient() { + ConnectionString connectionString = new ConnectionString(hostUri); + + CodecRegistry myRegistry = fromRegistries( + CodecRegistries.fromCodecs(new LiteralMapCodec(), new LiteralCodec()), + MongoClientSettings.getDefaultCodecRegistry(), + fromProviders( + PojoCodecProvider.builder() + .automatic(true) + .build() + ) + ); + + Block connectionPoolSettingsBlockBuilder = + (ConnectionPoolSettings.Builder builder) -> + builder.maxConnectionIdleTime(mongoMaxIdleTimeMillisec, TimeUnit.MILLISECONDS); + + return MongoClients.create( + MongoClientSettings.builder() + .applyConnectionString(connectionString) + .codecRegistry(myRegistry) + .applyToConnectionPoolSettings(connectionPoolSettingsBlockBuilder) + .build()); + } + + @Primary + @Bean(name = AppConfigConstants.BEAN_RECORD_DATA_STORE) + public Datastore emDataStore(MongoClient mongoClient) { + LOGGER.info("Configuring Record API database: {}", recordDatabase); + Datastore datastore = Morphia.createDatastore(mongoClient, recordDatabase, MapperOptions.builder().mapSubPackages(true).build()); + + // EA-2520: explicit package mapping required to prevent EntityDecoder error + // TODO switch the package to interfaces later , once ready + datastore.getMapper().mapPackage("eu.europeana.api.record.impl"); + datastore.ensureIndexes(); + return datastore; + } + +} diff --git a/record-api-mongo/src/main/java/eu/europeana/api/record/repository/AbstractRepository.java b/record-api-mongo/src/main/java/eu/europeana/api/record/repository/AbstractRepository.java new file mode 100644 index 0000000..df86ad4 --- /dev/null +++ b/record-api-mongo/src/main/java/eu/europeana/api/record/repository/AbstractRepository.java @@ -0,0 +1,17 @@ +package eu.europeana.api.record.repository; + +import dev.morphia.Datastore; +import eu.europeana.api.record.vocabulary.AppConfigConstants; + +import javax.annotation.Resource; + +public abstract class AbstractRepository { + + @Resource(name = AppConfigConstants.BEAN_RECORD_DATA_STORE) + Datastore datastore; + + + protected Datastore getDataStore() { + return datastore; + } +} diff --git a/record-api-mongo/src/main/java/eu/europeana/api/record/repository/RecordRepository.java b/record-api-mongo/src/main/java/eu/europeana/api/record/repository/RecordRepository.java new file mode 100644 index 0000000..213721c --- /dev/null +++ b/record-api-mongo/src/main/java/eu/europeana/api/record/repository/RecordRepository.java @@ -0,0 +1,72 @@ +package eu.europeana.api.record.repository; + +import dev.morphia.query.FindOptions; +import dev.morphia.query.filters.Filter; +import dev.morphia.query.filters.Filters; +import eu.europeana.api.record.Record; +import eu.europeana.api.record.vocabulary.AppConfigConstants; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.List; + +/** + * Record repository to storing and retrieving record data + * @author srishti singh + * @since 4 August 2023 + */ + +// TODO switch record class to < ? extends Record interface > once the interface is ready +@Repository(AppConfigConstants.BEAN_RECORD_REPO) +public class RecordRepository extends AbstractRepository { + + + /** + * Saves the given record to the database. + * + * @param record record to save + * @return saved record + */ + public Record save(Record record) { + return getDataStore().save(record); + } + + + /** @return the total number of records in the database */ + public long count() { + return getDataStore().find(java.lang.Record.class).count(); + } + + /** + * Check if an Record exists that matches the given parameters using DBCollection.count(). + * + * @param recordId ID of the dataset + * @return true if yes, otherwise false + */ + public boolean existsByRecordId(String recordId) { + return getDataStore() + .find(java.lang.Record.class) + .filter(Filters.eq("about", recordId)) + .count() + > 0; + } + + /** + * Find Record that matches the given record id + * + * @param recordId : Id of the record to be fetched + * @return record matching record id + */ + public java.lang.Record findById(String recordId) { + // Get all EntityRecords that match the given entityIds + List filters = new ArrayList<>(); + filters.add(Filters.eq("about", recordId)); + + return getDataStore() + .find(java.lang.Record.class) + .filter(filters.toArray(Filter[]::new)) + .iterator(new FindOptions()) + .tryNext(); + } + +} diff --git a/record-api-web/pom.xml b/record-api-web/pom.xml new file mode 100644 index 0000000..d5e34e7 --- /dev/null +++ b/record-api-web/pom.xml @@ -0,0 +1,136 @@ + + + + record-api + eu.europeana.api + 1.0-SNAPSHOT + + 4.0.0 + + record-api-web + The Web Module of the Record API + jar + + + ${java.version} + ${java.version} + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + io.springfox + springfox-boot-starter + ${swagger.version} + + + slf4j-api + org.slf4j + + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + + eu.europeana.api.commons + commons-web + ${api.commons.version} + + + org.mongodb + mongo-java-driver + + + xml-apis + xml-apis + + + + + + eu.europeana.api + record-api-mongo + 1.0-SNAPSHOT + + + + + + + + src/main/resources + true + + *.properties + */*.info + *.xml + + + **/*.jks + + + + src/main/resources + false + + **/*.jks + public/** + + + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + executable + + + + + + + + diff --git a/record-api-web/src/main/java/eu/europeana/api/record/RecordApp.java b/record-api-web/src/main/java/eu/europeana/api/record/RecordApp.java new file mode 100644 index 0000000..d02a04e --- /dev/null +++ b/record-api-web/src/main/java/eu/europeana/api/record/RecordApp.java @@ -0,0 +1,40 @@ +package eu.europeana.api.record; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; + + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** + * Main application. Allows deploying as a war and logs instance data when deployed in Cloud Foundry + */ +@SpringBootApplication( + scanBasePackages = {"eu.europeana.api.record"}, + exclude = { + // Remove these exclusions to re-enable security + SecurityAutoConfiguration.class, + ManagementWebSecurityAutoConfiguration.class, + // DataSources are manually configured (for EM and batch DBs) + DataSourceAutoConfiguration.class + }) +public class RecordApp { + + private static final Logger LOG = LogManager.getLogger(RecordApp.class); + + /** + * Main entry point of this application + * + * @param args command-line arguments + */ + public static void main(String[] args) { + LOG.info("No args provided to application. Starting web server"); + SpringApplication.run(RecordApp.class, args); + } + + +} diff --git a/record-api-web/src/main/java/eu/europeana/api/record/config/AppConfig.java b/record-api-web/src/main/java/eu/europeana/api/record/config/AppConfig.java new file mode 100644 index 0000000..6951ff2 --- /dev/null +++ b/record-api-web/src/main/java/eu/europeana/api/record/config/AppConfig.java @@ -0,0 +1,35 @@ +package eu.europeana.api.record.config; + +import eu.europeana.api.record.vocabulary.AppConfigConstants; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; + +@Configuration +public class AppConfig extends AppConfigConstants { + + private static final Logger LOG = LogManager.getLogger(AppConfig.class); + + @Resource + private RecordApiConfiguration recordApiConfiguration; + + public AppConfig() { + LOG.info("Initializing RecordApiConfiguration bean as: configuration"); + } + + + // TODO jwt authentication will be added later + @PostConstruct + public void init() { + if (recordApiConfiguration.isAuthReadEnabled() || recordApiConfiguration.isAuthWriteEnabled()) { + String jwtTokenSignatureKey = recordApiConfiguration.getApiKeyPublicKey(); + if (jwtTokenSignatureKey == null || jwtTokenSignatureKey.isBlank()) { + throw new IllegalStateException("The jwt token signature key cannot be null or empty."); + } + } + } + +} diff --git a/record-api-web/src/main/java/eu/europeana/api/record/config/RecordApiConfiguration.java b/record-api-web/src/main/java/eu/europeana/api/record/config/RecordApiConfiguration.java new file mode 100644 index 0000000..2725278 --- /dev/null +++ b/record-api-web/src/main/java/eu/europeana/api/record/config/RecordApiConfiguration.java @@ -0,0 +1,54 @@ +package eu.europeana.api.record.config; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; + +@Configuration +@PropertySources({ + @PropertySource("classpath:record-api.properties"), + @PropertySource( + value = "classpath:record-api.user.properties", + ignoreResourceNotFound = true) +}) +public class RecordApiConfiguration implements InitializingBean { + + private static final Logger LOG = LogManager.getLogger(RecordApiConfiguration.class); + + @Value("${europeana.apikey.jwttoken.signaturekey}") + private String apiKeyPublicKey; + + @Value("${europeana.apikey.serviceurl}") + private String apiKeyUrl; + + @Value("${auth.read.enabled: true}") + private boolean authReadEnabled; + + @Value("${auth.write.enabled: true}") + private boolean authWriteEnabled; + + public String getApiKeyUrl() { + return apiKeyUrl; + } + + public boolean isAuthReadEnabled() { + return authReadEnabled; + } + + public boolean isAuthWriteEnabled() { + return authWriteEnabled; + } + + public String getApiKeyPublicKey() { + return apiKeyPublicKey; + } + + @Override + public void afterPropertiesSet() throws Exception { + // TODO add validation of required properties + } +} diff --git a/record-api-web/src/main/java/eu/europeana/api/record/service/RecordService.java b/record-api-web/src/main/java/eu/europeana/api/record/service/RecordService.java new file mode 100644 index 0000000..29bb48a --- /dev/null +++ b/record-api-web/src/main/java/eu/europeana/api/record/service/RecordService.java @@ -0,0 +1,27 @@ +package eu.europeana.api.record.service; + +import eu.europeana.api.record.config.AppConfig; +import eu.europeana.api.record.config.RecordApiConfiguration; +import eu.europeana.api.record.Record; +import eu.europeana.api.record.repository.RecordRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service(AppConfig.BEAN_RECORD_SERVICE) +public class RecordService { + + private final RecordRepository recordRepository; + + final RecordApiConfiguration recordApiConfiguration; + + @Autowired + public RecordService(RecordRepository recordRepository, RecordApiConfiguration recordApiConfiguration) { + this.recordRepository = recordRepository; + this.recordApiConfiguration = recordApiConfiguration; + } + + public Record saveRecord(Record record) { + return recordRepository.save(record); + } + +} diff --git a/record-api-web/src/main/java/eu/europeana/api/record/web/RecordController.java b/record-api-web/src/main/java/eu/europeana/api/record/web/RecordController.java new file mode 100644 index 0000000..3f095c7 --- /dev/null +++ b/record-api-web/src/main/java/eu/europeana/api/record/web/RecordController.java @@ -0,0 +1,45 @@ +package eu.europeana.api.record.web; + +import eu.europeana.api.commons.web.http.HttpHeaders; +import eu.europeana.api.record.Record; +import eu.europeana.api.record.service.RecordService; +import io.swagger.annotations.ApiOperation; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Validated +public class RecordController { + + private final RecordService recordService; + + @Autowired + public RecordController(RecordService recordService) { + this.recordService = recordService; + } + + + @ApiOperation( + value = "Register a new record", + nickname = "registerRecord", + response = java.lang.Void.class) + @PostMapping( + value = "/record/", + produces = {MediaType.APPLICATION_JSON_VALUE, HttpHeaders.CONTENT_TYPE_JSONLD}) + public ResponseEntity registerEntity( + @RequestBody Record record, HttpServletRequest request) throws Exception { + + + System.out.println(record); + recordService.saveRecord(record); + + return null; + } + +} diff --git a/record-api-web/src/main/resources/record-api.properties b/record-api-web/src/main/resources/record-api.properties new file mode 100644 index 0000000..57ed182 --- /dev/null +++ b/record-api-web/src/main/resources/record-api.properties @@ -0,0 +1,12 @@ +## Record API properties file + +# mongo url +mongo.connectionUrl= +mongo.record.database= + + +europeana.apikey.serviceurl= + +europeana.apikey.jwttoken.signaturekey= +auth.read.enabled= +auth.write.enabled= \ No newline at end of file