Skip to content
Snippets Groups Projects
Commit d793e7be authored by Martin Lowe's avatar Martin Lowe :flag_ca: Committed by Martin Lowe
Browse files

Create a solution version endpoint #43


Added new endpoint for solution versions. Updated listings to import
data from new listing versions table. Updated quarkus to version 0.28.
Removed brittle ResourceDataType annotation.

Change-Id: I1f108666b10cfa55de098f74e586688b8656ab90
Signed-off-by: Martin Lowe's avatarMartin Lowe <martin.lowe@eclipse-foundation.org>
parent 2428a4b6
No related branches found
No related tags found
No related merge requests found
Showing
with 346 additions and 178 deletions
......@@ -38,11 +38,9 @@ public class Listing extends NodeBase {
private boolean foundationMember;
@SortableField(name = "installs_count")
@JsonbProperty("installs_count")
private long installsTotal;
@SortableField(name = "installs_count_recent")
@JsonbProperty("installs_count_recent")
private long installsRecent;
@SortableField
......@@ -64,7 +62,7 @@ public class Listing extends NodeBase {
private Organization organization;
private List<Author> authors;
private List<Tag> tags;
private List<SolutionVersion> versions;
private List<ListingVersion> versions;
/**
* Default constructor, sets lists to empty lists to stop null pointers
......@@ -180,6 +178,7 @@ public class Listing extends NodeBase {
/**
* @return the installsTotal
*/
@JsonbProperty("installs_count")
public long getInstallsTotal() {
return installsTotal;
}
......@@ -187,6 +186,7 @@ public class Listing extends NodeBase {
/**
* @param installsTotal the installsTotal to set
*/
@JsonbTransient
public void setInstallsTotal(long installsTotal) {
this.installsTotal = installsTotal;
}
......@@ -194,6 +194,7 @@ public class Listing extends NodeBase {
/**
* @return the installsRecent
*/
@JsonbProperty("installs_count_recent")
public long getInstallsRecent() {
return installsRecent;
}
......@@ -201,6 +202,7 @@ public class Listing extends NodeBase {
/**
* @param installsRecent the installsRecent to set
*/
@JsonbTransient
public void setInstallsRecent(long installsRecent) {
this.installsRecent = installsRecent;
}
......@@ -215,7 +217,6 @@ public class Listing extends NodeBase {
/**
* @param favoriteCount the favoriteCount to set
*/
@JsonbTransient
public void setFavoriteCount(long favoriteCount) {
this.favoriteCount = favoriteCount;
}
......@@ -368,14 +369,15 @@ public class Listing extends NodeBase {
/**
* @return the versions
*/
public List<SolutionVersion> getVersions() {
public List<ListingVersion> getVersions() {
return new ArrayList<>(versions);
}
/**
* @param versions the versions to set
*/
public void setVersions(List<SolutionVersion> versions) {
@JsonbTransient
public void setVersions(List<ListingVersion> versions) {
Objects.requireNonNull(versions);
this.versions = new ArrayList<>(versions);
}
......
......@@ -11,12 +11,14 @@ import java.util.List;
import java.util.Objects;
/**
* Domain object representing a marketplace listing solution version
* Domain object representing a marketplace listing version
*
* @author Martin Lowe
*/
public class SolutionVersion {
public class ListingVersion {
private String id;
private String listingId;
private String version;
private List<String> eclipseVersions;
private List<String> platforms;
......@@ -24,12 +26,40 @@ public class SolutionVersion {
private String updateSiteUrl;
private List<FeatureId> featureIds;
public SolutionVersion() {
public ListingVersion() {
this.eclipseVersions = new ArrayList<>();
this.platforms = new ArrayList<>();
this.featureIds = new ArrayList<>();
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the listingId
*/
public String getListingId() {
return listingId;
}
/**
* @param listingId the listingId to set
*/
public void setListingId(String listingId) {
this.listingId = listingId;
}
/**
* @return the versionString
*/
......@@ -106,14 +136,15 @@ public class SolutionVersion {
* @return the featureIds
*/
public List<FeatureId> getFeatureIds() {
return featureIds;
return new ArrayList<>(featureIds);
}
/**
* @param featureIds the featureIds to set
*/
public void setFeatureIds(List<FeatureId> featureIds) {
this.featureIds = featureIds;
Objects.requireNonNull(featureIds);
this.featureIds = new ArrayList<>(featureIds);
}
}
......@@ -23,7 +23,7 @@ import org.eclipsefoundation.marketplace.dto.Listing;
import org.eclipsefoundation.marketplace.dto.converters.AuthorConverter;
import org.eclipsefoundation.marketplace.dto.converters.CategoryConverter;
import org.eclipsefoundation.marketplace.dto.converters.OrganizationConverter;
import org.eclipsefoundation.marketplace.dto.converters.SolutionVersionConverter;
import org.eclipsefoundation.marketplace.dto.converters.ListingVersionConverter;
import org.eclipsefoundation.marketplace.dto.converters.TagConverter;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
......@@ -43,7 +43,7 @@ public class ListingCodec implements CollectibleCodec<Listing> {
private final AuthorConverter authorConverter;
private final OrganizationConverter organizationConverter;
private final TagConverter tagConverter;
private final SolutionVersionConverter versionConverter;
private final ListingVersionConverter versionConverter;
private final CategoryConverter categoryConverter;
/**
......@@ -55,7 +55,7 @@ public class ListingCodec implements CollectibleCodec<Listing> {
this.authorConverter = new AuthorConverter();
this.organizationConverter = new OrganizationConverter();
this.tagConverter = new TagConverter();
this.versionConverter = new SolutionVersionConverter();
this.versionConverter = new ListingVersionConverter();
this.categoryConverter = new CategoryConverter();
}
......@@ -90,8 +90,6 @@ public class ListingCodec implements CollectibleCodec<Listing> {
value.getAuthors().stream().map(authorConverter::convert).collect(Collectors.toList()));
doc.put(DatabaseFieldNames.LISTING_TAGS,
value.getTags().stream().map(tagConverter::convert).collect(Collectors.toList()));
doc.put(DatabaseFieldNames.LISTING_VERSIONS,
value.getVersions().stream().map(versionConverter::convert).collect(Collectors.toList()));
documentCodec.encode(writer, doc, encoderContext);
}
......
/* Copyright (c) 2019 Eclipse Foundation and others.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License 2.0
* which is available at http://www.eclipse.org/legal/epl-v20.html,
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipsefoundation.marketplace.dto.codecs;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.bson.BsonReader;
import org.bson.BsonString;
import org.bson.BsonValue;
import org.bson.BsonWriter;
import org.bson.Document;
import org.bson.codecs.Codec;
import org.bson.codecs.CollectibleCodec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.eclipsefoundation.marketplace.dto.ListingVersion;
import org.eclipsefoundation.marketplace.dto.converters.ListingVersionConverter;
import com.mongodb.MongoClient;
/**
* MongoDB codec for transcoding of {@link ListingVersion} and {@link Document}
* objects. Used when writing or retrieving objects of given type from the
* database.
*
* @author Martin Lowe
*/
public class ListingVersionCodec implements CollectibleCodec<ListingVersion> {
private final Codec<Document> documentCodec;
private ListingVersionConverter cc;
/**
* Creates the codec and initializes the codecs and converters needed to create
* a listing from end to end.
*/
public ListingVersionCodec() {
this.documentCodec = MongoClient.getDefaultCodecRegistry().get(Document.class);
this.cc = new ListingVersionConverter();
}
@Override
public void encode(BsonWriter writer, ListingVersion value, EncoderContext encoderContext) {
documentCodec.encode(writer, cc.convert(value), encoderContext);
}
@Override
public Class<ListingVersion> getEncoderClass() {
return ListingVersion.class;
}
@Override
public ListingVersion decode(BsonReader reader, DecoderContext decoderContext) {
return cc.convert(documentCodec.decode(reader, decoderContext));
}
@Override
public ListingVersion generateIdIfAbsentFromDocument(ListingVersion document) {
if (!documentHasId(document)) {
document.setId(UUID.randomUUID().toString());
}
return document;
}
@Override
public boolean documentHasId(ListingVersion document) {
return !StringUtils.isBlank(document.getId());
}
@Override
public BsonValue getDocumentId(ListingVersion document) {
return new BsonString(document.getId());
}
}
......@@ -9,21 +9,23 @@ package org.eclipsefoundation.marketplace.dto.converters;
import java.util.stream.Collectors;
import org.bson.Document;
import org.eclipsefoundation.marketplace.dto.SolutionVersion;
import org.eclipsefoundation.marketplace.dto.ListingVersion;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
/**
* Converter implementation for the {@link SolutionVersion} object.
* Converter implementation for the {@link ListingVersion} object.
*
* @author Martin Lowe
*/
public class SolutionVersionConverter implements Converter<SolutionVersion> {
public class ListingVersionConverter implements Converter<ListingVersion> {
private final FeatureIdConverter featureIdConverter = new FeatureIdConverter();
@Override
public SolutionVersion convert(Document src) {
SolutionVersion version = new SolutionVersion();
public ListingVersion convert(Document src) {
ListingVersion version = new ListingVersion();
version.setId(src.getString(DatabaseFieldNames.DOCID));
version.setListingId(src.getString(DatabaseFieldNames.LISTING_ID));
version.setEclipseVersions(src.getList("compatible_versions", String.class));
version.setPlatforms(src.getList("platforms", String.class));
version.setMinJavaVersion(src.getString("min_java_version"));
......@@ -35,8 +37,10 @@ public class SolutionVersionConverter implements Converter<SolutionVersion> {
}
@Override
public Document convert(SolutionVersion src) {
public Document convert(ListingVersion src) {
Document doc = new Document();
doc.put(DatabaseFieldNames.DOCID, src.getId());
doc.put(DatabaseFieldNames.LISTING_ID, src.getListingId());
doc.put("compatible_versions", src.getEclipseVersions());
doc.put("platforms", src.getPlatforms());
doc.put("min_java_version", src.getMinJavaVersion());
......
......@@ -30,12 +30,15 @@ import com.mongodb.client.model.Filters;
public class CatalogFilter implements DtoFilter<Catalog> {
@Override
public List<Bson> getFilters(RequestWrapper wrap) {
public List<Bson> getFilters(RequestWrapper wrap, String root) {
List<Bson> filters = new ArrayList<>();
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
// perform following checks only if there is no doc root
if (root == null) {
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
}
}
return filters;
}
......
......@@ -29,12 +29,15 @@ import com.mongodb.client.model.Filters;
public class CategoryFilter implements DtoFilter<Category> {
@Override
public List<Bson> getFilters(RequestWrapper wrap) {
public List<Bson> getFilters(RequestWrapper wrap, String root) {
List<Bson> filters = new ArrayList<>();
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
// perform following checks only if there is no doc root
if (root == null) {
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
}
}
return filters;
}
......
......@@ -7,10 +7,14 @@
package org.eclipsefoundation.marketplace.dto.filter;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.bson.conversions.Bson;
import org.eclipsefoundation.marketplace.model.RequestWrapper;
import com.mongodb.client.model.Aggregates;
/**
* Filter interface for usage when querying data.
*
......@@ -21,16 +25,19 @@ public interface DtoFilter<T> {
/**
* Retrieve filter objects for the current arguments.
*
* @param wrap wrapper for the current request
* @return list of filters for the current request, or empty if there are no applicable filters.
* @param wrap wrapper for the current request
* @param nestedPath current path for nesting of filters
* @return list of filters for the current request, or empty if there are no
* applicable filters.
*/
List<Bson> getFilters(RequestWrapper wrap);
List<Bson> getFilters(RequestWrapper wrap, String nestedPath);
/**
* Retrieve aggregate filter operations for the current arguments.
*
* @param wrap wrapper for the current request
* @return list of aggregates for the current request, or empty if there are no applicable aggregates.
* @param wrap wrapper for the current request
* @return list of aggregates for the current request, or empty if there are no
* applicable aggregates.
*/
List<Bson> getAggregates(RequestWrapper wrap);
......@@ -40,4 +47,28 @@ public interface DtoFilter<T> {
* @return class of object to filter
*/
Class<T> getType();
/**
* Wraps each of the filters present for a given filter type in an aggregate
* match operation to port filter operations into an aggregate pipeline. This is
* handy when importing nested types and enabling filters.
*
* @param wrap wrapper for the current request
* @param nestedPath current path for nesting of filters
* @return a list of aggregate pipeline operations representing the filters for
* the current request.
*/
default List<Bson> wrapFiltersToAggregate(RequestWrapper wrap, String nestedPath) {
return getFilters(wrap, nestedPath).stream().map(Aggregates::match).collect(Collectors.toList());
}
/**
*
* @param root
* @param fieldName
* @return
*/
default String getPath(String root, String fieldName) {
return StringUtils.isBlank(root) ? fieldName : root + '.' + fieldName;
}
}
......@@ -30,7 +30,7 @@ import com.mongodb.client.model.Filters;
public class ErrorReportFilter implements DtoFilter<ErrorReport> {
@Override
public List<Bson> getFilters(RequestWrapper wrap) {
public List<Bson> getFilters(RequestWrapper wrap, String root) {
List<Bson> filters = new ArrayList<>();
// ErrorReport ID check
......
......@@ -32,12 +32,15 @@ import com.mongodb.client.model.Filters;
public class InstallFilter implements DtoFilter<Install> {
@Override
public List<Bson> getFilters(RequestWrapper wrap) {
public List<Bson> getFilters(RequestWrapper wrap, String root) {
List<Bson> filters = new ArrayList<>();
// Listing ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.INSTALL_LISTING_ID, id.get()));
// perform following checks only if there is no doc root
if (root == null) {
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
}
}
// version check
Optional<String> version = wrap.getFirstParam(UrlParameterNames.VERSION);
......
......@@ -11,9 +11,11 @@ import java.util.List;
import java.util.Optional;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.bson.conversions.Bson;
import org.eclipsefoundation.marketplace.dto.Listing;
import org.eclipsefoundation.marketplace.dto.ListingVersion;
import org.eclipsefoundation.marketplace.model.RequestWrapper;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
import org.eclipsefoundation.marketplace.namespace.DtoTableNames;
......@@ -23,35 +25,26 @@ import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Filters;
/**
* Filter implementation for the Listing class. Checks the following fields:
*
* <ul>
* <li>platform_version
* <li>java_version
* <li>os
* <li>license_type
* <li>q
* <li>ids
* <li>tags
* </ul>
*
* <p>
* Injects categories into the results by way of aggregate pipeline.
* </p>
* Filter implementation for the {@linkplain Listing} class.
*
* @author Martin Lowe
*/
@ApplicationScoped
public class ListingFilter implements DtoFilter<Listing> {
@Inject
DtoFilter<ListingVersion> listingVersionFilter;
@Override
public List<Bson> getFilters(RequestWrapper wrap) {
public List<Bson> getFilters(RequestWrapper wrap, String root) {
List<Bson> filters = new ArrayList<>();
// Listing ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
// perform following checks only if there is no doc root
if (root == null) {
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
}
}
// select by multiple IDs
......@@ -66,29 +59,6 @@ public class ListingFilter implements DtoFilter<Listing> {
filters.add(Filters.eq(DatabaseFieldNames.LICENSE_TYPE, licType.get()));
}
// handle version sub document selection
List<Bson> versionFilters = new ArrayList<>();
// solution version - OS filter
Optional<String> os = wrap.getFirstParam(UrlParameterNames.OS);
if (os.isPresent()) {
versionFilters.add(Filters.eq("platforms", os.get()));
}
// solution version - eclipse version
Optional<String> eclipseVersion = wrap.getFirstParam(UrlParameterNames.ECLIPSE_VERSION);
if (eclipseVersion.isPresent()) {
versionFilters.add(Filters.eq("compatible_versions", eclipseVersion.get()));
}
// TODO this sorts by naturally by character rather than by actual number (e.g.
// 1.9 is technically greater than 1.10)
// solution version - Java version
Optional<String> javaVersion = wrap.getFirstParam(UrlParameterNames.JAVA_VERSION);
if (javaVersion.isPresent()) {
versionFilters.add(Filters.gte("min_java_version", javaVersion.get()));
}
if (!versionFilters.isEmpty()) {
filters.add(Filters.elemMatch("versions", Filters.and(versionFilters)));
}
// select by multiple tags
List<String> tags = wrap.getParams(UrlParameterNames.TAGS);
if (!tags.isEmpty()) {
......@@ -107,6 +77,9 @@ public class ListingFilter implements DtoFilter<Listing> {
public List<Bson> getAggregates(RequestWrapper wrap) {
List<Bson> aggs = new ArrayList<>();
// adds a $lookup aggregate, joining categories on categoryIDS as "categories"
aggs.add(Aggregates.lookup(DtoTableNames.LISTING_VERSION.getTableName(), DatabaseFieldNames.DOCID, DatabaseFieldNames.LISTING_ID,
DatabaseFieldNames.LISTING_VERSIONS));
aggs.addAll(listingVersionFilter.wrapFiltersToAggregate(wrap, DatabaseFieldNames.LISTING_VERSIONS));
aggs.add(Aggregates.lookup(DtoTableNames.CATEGORY.getTableName(), DatabaseFieldNames.CATEGORY_IDS, DatabaseFieldNames.DOCID,
DatabaseFieldNames.LISTING_CATEGORIES));
List<String> marketIds = wrap.getParams(UrlParameterNames.MARKET_IDS);
......
/* Copyright (c) 2019 Eclipse Foundation and others.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License 2.0
* which is available at http://www.eclipse.org/legal/epl-v20.html,
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipsefoundation.marketplace.dto.filter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.enterprise.context.ApplicationScoped;
import org.bson.conversions.Bson;
import org.eclipsefoundation.marketplace.dto.ListingVersion;
import org.eclipsefoundation.marketplace.model.RequestWrapper;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
import org.eclipsefoundation.marketplace.namespace.UrlParameterNames;
import com.mongodb.client.model.Filters;
/**
* Filter implementation for the {@linkplain ListingVersion} class.
*
* @author Martin Lowe
*
*/
@ApplicationScoped
public class ListingVersionFilter implements DtoFilter<ListingVersion> {
@Override
public List<Bson> getFilters(RequestWrapper wrap, String root) {
List<Bson> filters = new ArrayList<>();
// perform following checks only if there is no doc root
if (root == null) {
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
}
}
// solution version - OS filter
Optional<String> os = wrap.getFirstParam(UrlParameterNames.OS);
if (os.isPresent()) {
filters.add(Filters.eq(getPath(root, "platforms"), os.get()));
}
// solution version - eclipse version
Optional<String> eclipseVersion = wrap.getFirstParam(UrlParameterNames.ECLIPSE_VERSION);
if (eclipseVersion.isPresent()) {
filters.add(Filters.eq(getPath(root, "compatible_versions"), eclipseVersion.get()));
}
// TODO this sorts by naturally by character rather than by actual number (e.g.
// 1.9 is technically greater than 1.10)
// solution version - Java version
Optional<String> javaVersion = wrap.getFirstParam(UrlParameterNames.JAVA_VERSION);
if (javaVersion.isPresent()) {
filters.add(Filters.gte(getPath(root, "min_java_version"), javaVersion.get()));
}
return filters;
}
@Override
public List<Bson> getAggregates(RequestWrapper wrap) {
return Collections.emptyList();
}
@Override
public Class<ListingVersion> getType() {
return ListingVersion.class;
}
}
......@@ -27,6 +27,7 @@ import org.eclipsefoundation.marketplace.namespace.UrlParameterNames;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Variable;
......@@ -39,12 +40,15 @@ import com.mongodb.client.model.Variable;
public class MarketFilter implements DtoFilter<Market> {
@Override
public List<Bson> getFilters(RequestWrapper wrap) {
public List<Bson> getFilters(RequestWrapper wrap, String root) {
List<Bson> filters = new ArrayList<>();
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(eq(DatabaseFieldNames.DOCID, id.get()));
// perform following checks only if there is no doc root
if (root == null) {
// ID check
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
}
}
return filters;
}
......@@ -63,7 +67,7 @@ public class MarketFilter implements DtoFilter<Market> {
Projections.fields(Projections.excludeId(), Projections.include(DatabaseFieldNames.CATEGORY_IDS))));
// set up a var reference for the _id
Variable<String> id = new Variable<String>("market_id", "$" + DatabaseFieldNames.DOCID);
Variable<String> id = new Variable<>("market_id", "$" + DatabaseFieldNames.DOCID);
// lookup all category IDS from listings with the given market ID
aggs.add(Aggregates.lookup(DtoTableNames.LISTING.getTableName(), Arrays.asList(id), pipeline, tempFieldName));
// explode all category IDS for collection
......
/* Copyright (c) 2019 Eclipse Foundation and others.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License 2.0
* which is available at http://www.eclipse.org/legal/epl-v20.html,
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipsefoundation.marketplace.dto.providers;
import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecProvider;
import org.bson.codecs.configuration.CodecRegistry;
import org.eclipsefoundation.marketplace.dto.Listing;
import org.eclipsefoundation.marketplace.dto.ListingVersion;
import org.eclipsefoundation.marketplace.dto.codecs.ListingCodec;
import org.eclipsefoundation.marketplace.dto.codecs.ListingVersionCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides the {@link ListingCodec} to MongoDB for conversions of
* {@link Listing} objects.
*
* @author Martin Lowe
*/
public class ListingVersionCodecProvider implements CodecProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(ListingVersionCodecProvider.class);
@SuppressWarnings("unchecked")
@Override
public <T> Codec<T> get(Class<T> clazz, CodecRegistry registry) {
if (clazz == ListingVersion.class) {
LOGGER.debug("Registering custom Listing class MongoDB codec");
return (Codec<T>) new ListingVersionCodec();
}
return null;
}
}
......@@ -17,7 +17,6 @@ import org.eclipsefoundation.marketplace.dto.filter.DtoFilter;
import org.eclipsefoundation.marketplace.helper.SortableHelper;
import org.eclipsefoundation.marketplace.helper.SortableHelper.Sortable;
import org.eclipsefoundation.marketplace.namespace.UrlParameterNames;
import org.eclipsefoundation.marketplace.resource.AnnotationClassInjectionFilter;
import org.eclipsefoundation.marketplace.service.CachingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -50,7 +49,6 @@ public class MongoQuery<T> {
this.dtoFilter = dtoFilter;
this.cache = cache;
this.aggregates = new ArrayList<>();
init();
}
......@@ -68,7 +66,7 @@ public class MongoQuery<T> {
// get the filters for the current DTO
List<Bson> filters = new ArrayList<>();
filters.addAll(dtoFilter.getFilters(wrapper));
filters.addAll(dtoFilter.getFilters(wrapper, null));
// get fields that make up the required fields to enable pagination and check
Optional<String> sortOpt = wrapper.getFirstParam(UrlParameterNames.SORT);
......@@ -186,7 +184,7 @@ public class MongoQuery<T> {
* @return the docType
*/
public Class<T> getDocType() {
return (Class<T>) wrapper.getAttribute(AnnotationClassInjectionFilter.ATTRIBUTE_NAME).get();
return dtoFilter.getType();
}
/**
......
/* Copyright (c) 2019 Eclipse Foundation and others.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License 2.0
* which is available at http://www.eclipse.org/legal/epl-v20.html,
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipsefoundation.marketplace.model;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
*
* @author Martin Lowe
*/
@Retention(RUNTIME)
@Target(TYPE)
public @interface ResourceDataType {
Class<?> value();
}
......@@ -8,10 +8,11 @@ package org.eclipsefoundation.marketplace.namespace;
import org.eclipsefoundation.marketplace.dto.Catalog;
import org.eclipsefoundation.marketplace.dto.Category;
import org.eclipsefoundation.marketplace.dto.ErrorReport;
import org.eclipsefoundation.marketplace.dto.Install;
import org.eclipsefoundation.marketplace.dto.Listing;
import org.eclipsefoundation.marketplace.dto.ListingVersion;
import org.eclipsefoundation.marketplace.dto.Market;
import org.eclipsefoundation.marketplace.dto.ErrorReport;
/**
* Mapping of DTO classes to their respective tables in the DB.
......@@ -20,10 +21,9 @@ import org.eclipsefoundation.marketplace.dto.ErrorReport;
*
*/
public enum DtoTableNames {
LISTING(Listing.class, "listings"),
CATEGORY(Category.class, "categories"),
CATALOG(Catalog.class, "catalogs"), MARKET(Market.class, "markets"),
ERRORREPORT(ErrorReport.class, "errorreports"), INSTALL(Install.class, "installs");
LISTING(Listing.class, "listings"), CATEGORY(Category.class, "categories"), CATALOG(Catalog.class, "catalogs"),
MARKET(Market.class, "markets"), ERRORREPORT(ErrorReport.class, "errorreports"), INSTALL(Install.class, "installs"),
LISTING_VERSION(ListingVersion.class, "listing_versions");
private Class<?> baseClass;
private String tableName;
......
/* Copyright (c) 2019 Eclipse Foundation and others.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License 2.0
* which is available at http://www.eclipse.org/legal/epl-v20.html,
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipsefoundation.marketplace.resource;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import org.eclipsefoundation.marketplace.model.ResourceDataType;
/**
* Pre-processes the request to inject the datatype class name into the request.
* This is later used in reflection to circumvent type erasure within Query
* objects.
*
* @author Martin Lowe
*/
@Provider
public class AnnotationClassInjectionFilter implements ContainerRequestFilter {
public static final String ATTRIBUTE_NAME = "enclosed-data-type";
@Context
HttpServletRequest request;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
List<Object> resources = requestContext.getUriInfo().getMatchedResources();
if (!resources.isEmpty()) {
// Quarkus compiles wrapper classes around beans, needs superclass call to get original class
Class<?> clazz = resources.get(0).getClass().getSuperclass();
// get the resource data type
ResourceDataType[] dataTypes = clazz.getAnnotationsByType(ResourceDataType.class);
if (dataTypes.length > 0) {
ResourceDataType firstType = dataTypes[0];
request.setAttribute(ATTRIBUTE_NAME, firstType.value());
}
}
}
}
......@@ -29,7 +29,6 @@ import org.eclipsefoundation.marketplace.helper.StreamHelper;
import org.eclipsefoundation.marketplace.model.Error;
import org.eclipsefoundation.marketplace.model.MongoQuery;
import org.eclipsefoundation.marketplace.model.RequestWrapper;
import org.eclipsefoundation.marketplace.model.ResourceDataType;
import org.eclipsefoundation.marketplace.namespace.UrlParameterNames;
import org.eclipsefoundation.marketplace.service.CachingService;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
......@@ -42,7 +41,6 @@ import com.mongodb.client.result.DeleteResult;
* @author martin
*
*/
@ResourceDataType(Catalog.class)
@Path("/catalogs")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
......
......@@ -29,7 +29,6 @@ import org.eclipsefoundation.marketplace.helper.StreamHelper;
import org.eclipsefoundation.marketplace.model.Error;
import org.eclipsefoundation.marketplace.model.MongoQuery;
import org.eclipsefoundation.marketplace.model.RequestWrapper;
import org.eclipsefoundation.marketplace.model.ResourceDataType;
import org.eclipsefoundation.marketplace.namespace.UrlParameterNames;
import org.eclipsefoundation.marketplace.service.CachingService;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
......@@ -42,7 +41,6 @@ import com.mongodb.client.result.DeleteResult;
* @author martin
*
*/
@ResourceDataType(Category.class)
@Path("/categories")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment