Skip to content
Snippets Groups Projects
Commit d16bcf88 authored by Martin Lowe's avatar Martin Lowe :flag_ca: Committed by Mikaël Barbero
Browse files

Added Market resource, package name update, code clean up


Change-Id: Ib8d095f06d59209ed894a1048a4ca8415b81c59a
Signed-off-by: Martin Lowe's avatarMartin Lowe <martin.lowe@eclipse-foundation.org>
parent ef83d5ab
No related branches found
No related tags found
No related merge requests found
Showing
with 561 additions and 217 deletions
......@@ -181,6 +181,11 @@
"ansi-regex": "^4.1.0"
}
},
"uuid": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
......
......@@ -12,6 +12,7 @@
"dependencies": {
"axios": "^0.19.0",
"random-words": "^1.1.0",
"uuid": "^3.3.3",
"yargs": "^14.0.0"
}
}
......@@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipsefoundation</groupId>
<artifactId>marketplace-rest-api</artifactId>
<version>0.1-ALPHA</version>
<version>0.2-BETA</version>
<properties>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<surefire-plugin.version>2.22.0</surefire-plugin.version>
......
......@@ -60,8 +60,6 @@ public class DefaultMongoDao implements MongoDao {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Querying MongoDB using the following query: {}", q);
}
LOGGER.error("{}", q);
LOGGER.debug("Getting aggregate results");
return getCollection(q.getDocType()).aggregate(q.getPipeline(getLimit(q)), q.getDocType()).limit(getLimit(q))
......
......@@ -9,8 +9,7 @@
*/
package org.eclipsefoundation.marketplace.dto;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import io.quarkus.runtime.annotations.RegisterForReflection;
......@@ -22,22 +21,21 @@ import io.quarkus.runtime.annotations.RegisterForReflection;
*/
@RegisterForReflection
public class Category {
private Integer id;
private String id;
private String name;
private String url;
private List<Integer> marketIds;
/**
* @return the id
*/
public int getId() {
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
public void setId(String id) {
this.id = id;
}
......@@ -69,58 +67,24 @@ public class Category {
this.url = url;
}
/**
* @return the marketIds
*/
public List<Integer> getMarketIds() {
return new ArrayList<>(marketIds);
}
/**
* @param marketIds the marketIds to set
*/
public void setMarketIds(List<Integer> marketIds) {
this.marketIds = new ArrayList<>(marketIds);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((marketIds == null) ? 0 : marketIds.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((url == null) ? 0 : url.hashCode());
return result;
return Objects.hash(id, name, url);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
if (this == obj) {
return true;
if (obj == null)
}
if (obj == null) {
return false;
if (getClass() != obj.getClass())
}
if (getClass() != obj.getClass()) {
return false;
}
Category other = (Category) obj;
if (id != other.id)
return false;
if (marketIds == null) {
if (other.marketIds != null)
return false;
} else if (!marketIds.equals(other.marketIds))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (url == null) {
if (other.url != null)
return false;
} else if (!url.equals(other.url))
return false;
return true;
return Objects.equals(id, other.id) && Objects.equals(name, other.name) && Objects.equals(url, other.url);
}
@Override
......@@ -132,8 +96,6 @@ public class Category {
builder.append(name);
builder.append(", url=");
builder.append(url);
builder.append(", marketIds=");
builder.append(marketIds);
builder.append("]");
return builder.toString();
}
......
......@@ -8,6 +8,9 @@ package org.eclipsefoundation.marketplace.dto;
import java.sql.Date;
import org.eclipsefoundation.marketplace.model.RequestWrapper;
import org.eclipsefoundation.marketplace.namespace.UrlParameterNames;
/**
* Domain object representing the data stored for installs.
*
......@@ -18,9 +21,17 @@ public class Install {
private Date installDate;
private String os;
private String version;
private int listingId;
private String listingId;
private String javaVersion;
public static Install createFromRequest(RequestWrapper wrap) {
Install install = new Install();
install.installDate = new Date(System.currentTimeMillis());
install.listingId = wrap.getFirstParam(UrlParameterNames.ID).get();
return install;
}
/**
* @return the installDate
*/
......@@ -66,14 +77,14 @@ public class Install {
/**
* @return the listingId
*/
public int getListingId() {
public String getListingId() {
return listingId;
}
/**
* @param listingId the listingId to set
*/
public void setListingId(int listingId) {
public void setListingId(String listingId) {
this.listingId = listingId;
}
......
......@@ -17,7 +17,7 @@ import javax.json.bind.annotation.JsonbProperty;
import javax.json.bind.annotation.JsonbTransient;
import org.eclipsefoundation.marketplace.model.SortableField;
import org.eclipsefoundation.marketplace.namespace.MongoFieldNames;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
import io.quarkus.runtime.annotations.RegisterForReflection;
......@@ -29,10 +29,7 @@ import io.quarkus.runtime.annotations.RegisterForReflection;
@RegisterForReflection
public class Listing {
@JsonbTransient
private String id;
@SortableField(name = "listing_id")
private long listingId;
@SortableField
private String title;
private String url;
......@@ -55,16 +52,16 @@ public class Listing {
@SortableField
private long favoriteCount;
@SortableField(name = MongoFieldNames.CREATION_DATE)
@JsonbProperty(MongoFieldNames.CREATION_DATE)
@SortableField(name = DatabaseFieldNames.CREATION_DATE)
@JsonbProperty(DatabaseFieldNames.CREATION_DATE)
private long creationDate;
@SortableField(name = MongoFieldNames.UPDATE_DATE)
@JsonbProperty(MongoFieldNames.UPDATE_DATE)
@SortableField(name = DatabaseFieldNames.UPDATE_DATE)
@JsonbProperty(DatabaseFieldNames.UPDATE_DATE)
private long updateDate;
@JsonbProperty(MongoFieldNames.LICENSE_TYPE)
@JsonbProperty(DatabaseFieldNames.LICENSE_TYPE)
private String license;
private List<Integer> categoryIds;
private List<String> categoryIds;
private List<Category> categories;
private List<Organization> organizations;
private List<Author> authors;
......@@ -96,21 +93,7 @@ public class Listing {
public void setId(String id) {
this.id = id;
}
/**
* @return the listingId
*/
public long getListingId() {
return listingId;
}
/**
* @param listingId the id to set
*/
public void setListingId(long listingId) {
this.listingId = listingId;
}
/**
* @return the title
*/
......@@ -325,14 +308,15 @@ public class Listing {
/**
* @return the categoryIds
*/
public List<Integer> getCategoryIds() {
@JsonbTransient
public List<String> getCategoryIds() {
return categoryIds;
}
/**
* @param categoryIds the categoryIds to set
*/
public void setCategoryIds(List<Integer> categoryIds) {
public void setCategoryIds(List<String> categoryIds) {
this.categoryIds = new ArrayList<>(categoryIds);
}
......@@ -411,11 +395,42 @@ public class Listing {
this.versions = new ArrayList<>(versions);
}
@Override
public int hashCode() {
return Objects.hash(authors, body, categories, categoryIds, creationDate, favoriteCount, foundationMember,
homepageUrl, id, installsRecent, installsTotal, license, logo, organizations, status, supportUrl, tags,
teaser, title, updateDate, url, versions);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Listing other = (Listing) obj;
return Objects.equals(authors, other.authors) && Objects.equals(body, other.body)
&& Objects.equals(categories, other.categories) && Objects.equals(categoryIds, other.categoryIds)
&& creationDate == other.creationDate && favoriteCount == other.favoriteCount
&& foundationMember == other.foundationMember && Objects.equals(homepageUrl, other.homepageUrl)
&& Objects.equals(id, other.id) && installsRecent == other.installsRecent
&& installsTotal == other.installsTotal && Objects.equals(license, other.license)
&& Objects.equals(logo, other.logo) && Objects.equals(organizations, other.organizations)
&& Objects.equals(status, other.status) && Objects.equals(supportUrl, other.supportUrl)
&& Objects.equals(tags, other.tags) && Objects.equals(teaser, other.teaser)
&& Objects.equals(title, other.title) && updateDate == other.updateDate
&& Objects.equals(url, other.url) && Objects.equals(versions, other.versions);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(", id=").append(id);
sb.append(", listingId=").append(listingId);
sb.append(", title=").append(title);
sb.append(", url=").append(url);
sb.append(", supportUrl=").append(supportUrl);
......
......@@ -9,11 +9,11 @@
*/
package org.eclipsefoundation.marketplace.dto;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import javax.json.bind.annotation.JsonbTransient;
import io.quarkus.runtime.annotations.RegisterForReflection;
......@@ -25,9 +25,10 @@ import io.quarkus.runtime.annotations.RegisterForReflection;
*/
@RegisterForReflection
public class Market {
private int id;
private String id;
private String name;
private String url;
private List<String> categoryIds;
private List<Category> categories;
/**
......@@ -36,19 +37,20 @@ public class Market {
*/
public Market() {
this.categories = new LinkedList<>();
this.categoryIds = new LinkedList<>();
}
/**
* @return the id
*/
public int getId() {
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
public void setId(String id) {
this.id = id;
}
......@@ -90,36 +92,23 @@ public class Market {
/**
* @param categories the categories to set
*/
@JsonbTransient
public void setCategories(List<Category> categories) {
this.categories = new ArrayList<>(categories);
}
/**
* Remove a category from the market definition.
*
* @param c the category to remove if present
* @return the category removed if it was present, or null if it was missing.
* @throws InvalidParameterException if the passed category is an illegal value
* (i.e. null)
* @return the categoryIds
*/
public Category removeCategory(Category c) {
int idx = categories.indexOf(c);
if (idx > 0) {
return this.categories.remove(idx);
} else {
return null;
}
@JsonbTransient
public List<String> getCategoryIds() {
return new ArrayList<>(categoryIds);
}
/**
* Add a category to the market definition.
*
* @param c the category to add
* @throws IllegalArgumentException if the passed category is an illegal value
* (i.e. null)
* @param categoryIds the categoryIds to set
*/
public void addCategory(Category c) {
Objects.requireNonNull(c);
this.categories.add(c);
public void setCategoryIds(List<String> categoryIds) {
this.categoryIds = new ArrayList<>(categoryIds);
}
}
......@@ -6,6 +6,7 @@
*/
package org.eclipsefoundation.marketplace.dto.codecs;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bson.BsonReader;
......@@ -19,7 +20,7 @@ import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.eclipsefoundation.marketplace.dto.Catalog;
import org.eclipsefoundation.marketplace.dto.converters.TabConverter;
import org.eclipsefoundation.marketplace.namespace.MongoFieldNames;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
import com.mongodb.MongoClient;
......@@ -49,14 +50,14 @@ public class CatalogCodec implements CollectibleCodec<Catalog> {
public void encode(BsonWriter writer, Catalog value, EncoderContext encoderContext) {
Document doc = new Document();
doc.put(MongoFieldNames.DOCID, value.getId());
doc.put(MongoFieldNames.CATALOG_TITLE, value.getTitle());
doc.put(MongoFieldNames.CATALOG_URL, value.getUrl());
doc.put(MongoFieldNames.CATALOG_ICON, value.getIcon());
doc.put(MongoFieldNames.CATALOG_SELF_CONTAINED, value.isSelfContained());
doc.put(MongoFieldNames.CATALOG_SEARCH_ENABLED, value.isSearchEnabled());
doc.put(MongoFieldNames.CATALOG_DEPENDENCIES_REPOSITORY, value.getDependenciesRepository());
doc.put(MongoFieldNames.CATALOG_TABS,
doc.put(DatabaseFieldNames.DOCID, value.getId());
doc.put(DatabaseFieldNames.CATALOG_TITLE, value.getTitle());
doc.put(DatabaseFieldNames.CATALOG_URL, value.getUrl());
doc.put(DatabaseFieldNames.CATALOG_ICON, value.getIcon());
doc.put(DatabaseFieldNames.CATALOG_SELF_CONTAINED, value.isSelfContained());
doc.put(DatabaseFieldNames.CATALOG_SEARCH_ENABLED, value.isSearchEnabled());
doc.put(DatabaseFieldNames.CATALOG_DEPENDENCIES_REPOSITORY, value.getDependenciesRepository());
doc.put(DatabaseFieldNames.CATALOG_TABS,
value.getTabs().stream().map(tabConverter::convert).collect(Collectors.toList()));
documentCodec.encode(writer, doc, encoderContext);
}
......@@ -70,20 +71,23 @@ public class CatalogCodec implements CollectibleCodec<Catalog> {
public Catalog decode(BsonReader reader, DecoderContext decoderContext) {
Document document = documentCodec.decode(reader, decoderContext);
Catalog out = new Catalog();
out.setId(document.getString(MongoFieldNames.DOCID));
out.setUrl(document.getString(MongoFieldNames.CATALOG_URL));
out.setTitle(document.getString(MongoFieldNames.CATALOG_TITLE));
out.setIcon(document.getString(MongoFieldNames.CATALOG_ICON));
out.setSelfContained(document.getBoolean(MongoFieldNames.CATALOG_SELF_CONTAINED));
out.setSearchEnabled(document.getBoolean(MongoFieldNames.CATALOG_SEARCH_ENABLED));
out.setDependenciesRepository(document.getString(MongoFieldNames.CATALOG_DEPENDENCIES_REPOSITORY));
out.setTabs(document.getList(MongoFieldNames.CATALOG_TABS, Document.class).stream().map(tabConverter::convert)
out.setId(document.getString(DatabaseFieldNames.DOCID));
out.setUrl(document.getString(DatabaseFieldNames.CATALOG_URL));
out.setTitle(document.getString(DatabaseFieldNames.CATALOG_TITLE));
out.setIcon(document.getString(DatabaseFieldNames.CATALOG_ICON));
out.setSelfContained(document.getBoolean(DatabaseFieldNames.CATALOG_SELF_CONTAINED));
out.setSearchEnabled(document.getBoolean(DatabaseFieldNames.CATALOG_SEARCH_ENABLED));
out.setDependenciesRepository(document.getString(DatabaseFieldNames.CATALOG_DEPENDENCIES_REPOSITORY));
out.setTabs(document.getList(DatabaseFieldNames.CATALOG_TABS, Document.class).stream().map(tabConverter::convert)
.collect(Collectors.toList()));
return out;
}
@Override
public Catalog generateIdIfAbsentFromDocument(Catalog document) {
if (!documentHasId(document)) {
document.setId(UUID.randomUUID().toString());
}
return document;
}
......@@ -94,7 +98,6 @@ public class CatalogCodec implements CollectibleCodec<Catalog> {
@Override
public BsonValue getDocumentId(Catalog document) {
// TODO Auto-generated method stub
return new BsonString(document.getId());
}
......
......@@ -6,8 +6,11 @@
*/
package org.eclipsefoundation.marketplace.dto.codecs;
import org.bson.BsonInt32;
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;
......@@ -55,18 +58,20 @@ public class CategoryCodec implements CollectibleCodec<Category> {
@Override
public Category generateIdIfAbsentFromDocument(Category document) {
// TODO Auto-generated method stub
if (!documentHasId(document)) {
document.setId(UUID.randomUUID().toString());
}
return document;
}
@Override
public boolean documentHasId(Category document) {
return document.getId() > 0;
return !StringUtils.isBlank(document.getId());
}
@Override
public BsonValue getDocumentId(Category document) {
return new BsonInt32(document.getId());
return new BsonString(document.getId());
}
}
......@@ -25,7 +25,7 @@ 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.TagConverter;
import org.eclipsefoundation.marketplace.namespace.MongoFieldNames;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
import com.mongodb.MongoClient;
......@@ -64,33 +64,32 @@ public class ListingCodec implements CollectibleCodec<Listing> {
Document doc = new Document();
// for each of the fields, get the value from the unencoded object and set it
doc.put(MongoFieldNames.DOCID, value.getId());
doc.put(MongoFieldNames.LISTING_ID, value.getListingId());
doc.put(MongoFieldNames.LISTING_TITLE, value.getTitle());
doc.put(MongoFieldNames.LISTING_URL, value.getUrl());
doc.put(MongoFieldNames.SUPPORT_PAGE_URL, value.getSupportUrl());
doc.put(MongoFieldNames.HOME_PAGE_URL, value.getHomepageUrl());
doc.put(MongoFieldNames.LISTING_BODY, value.getTeaser());
doc.put(MongoFieldNames.LISTING_TEASER, value.getBody());
doc.put(MongoFieldNames.MARKETPLACE_FAVORITES, value.getFavoriteCount());
doc.put(MongoFieldNames.RECENT_NSTALLS, value.getInstallsRecent());
doc.put(MongoFieldNames.TOTAL_NSTALLS, value.getInstallsTotal());
doc.put(MongoFieldNames.LICENSE_TYPE, value.getLicense());
doc.put(MongoFieldNames.LISTING_STATUS, value.getStatus());
doc.put(MongoFieldNames.UPDATE_DATE, new Date(value.getUpdateDate()));
doc.put(MongoFieldNames.CREATION_DATE, new Date(value.getCreationDate()));
doc.put(MongoFieldNames.FOUNDATION_MEMBER_FLAG, value.isFoundationMember());
doc.put(MongoFieldNames.CATEGORY_IDS, value.getCategoryIds());
doc.put(DatabaseFieldNames.DOCID, value.getId());
doc.put(DatabaseFieldNames.LISTING_TITLE, value.getTitle());
doc.put(DatabaseFieldNames.URL, value.getUrl());
doc.put(DatabaseFieldNames.SUPPORT_PAGE_URL, value.getSupportUrl());
doc.put(DatabaseFieldNames.HOME_PAGE_URL, value.getHomepageUrl());
doc.put(DatabaseFieldNames.LISTING_BODY, value.getTeaser());
doc.put(DatabaseFieldNames.LISTING_TEASER, value.getBody());
doc.put(DatabaseFieldNames.MARKETPLACE_FAVORITES, value.getFavoriteCount());
doc.put(DatabaseFieldNames.RECENT_NSTALLS, value.getInstallsRecent());
doc.put(DatabaseFieldNames.TOTAL_NSTALLS, value.getInstallsTotal());
doc.put(DatabaseFieldNames.LICENSE_TYPE, value.getLicense());
doc.put(DatabaseFieldNames.LISTING_STATUS, value.getStatus());
doc.put(DatabaseFieldNames.UPDATE_DATE, new Date(value.getUpdateDate()));
doc.put(DatabaseFieldNames.CREATION_DATE, new Date(value.getCreationDate()));
doc.put(DatabaseFieldNames.FOUNDATION_MEMBER_FLAG, value.isFoundationMember());
doc.put(DatabaseFieldNames.CATEGORY_IDS, value.getCategoryIds());
// for nested document types, use the converters to safely transform into BSON
// documents
doc.put(MongoFieldNames.LISTING_ORGANIZATIONS,
doc.put(DatabaseFieldNames.LISTING_ORGANIZATIONS,
value.getOrganizations().stream().map(organizationConverter::convert).collect(Collectors.toList()));
doc.put(MongoFieldNames.LISTING_AUTHORS,
doc.put(DatabaseFieldNames.LISTING_AUTHORS,
value.getAuthors().stream().map(authorConverter::convert).collect(Collectors.toList()));
doc.put(MongoFieldNames.LISTING_TAGS,
doc.put(DatabaseFieldNames.LISTING_TAGS,
value.getTags().stream().map(tagConverter::convert).collect(Collectors.toList()));
doc.put(MongoFieldNames.LISTING_VERSIONS,
doc.put(DatabaseFieldNames.LISTING_VERSIONS,
value.getVersions().stream().map(versionConverter::convert).collect(Collectors.toList()));
documentCodec.encode(writer, doc, encoderContext);
}
......@@ -106,37 +105,36 @@ public class ListingCodec implements CollectibleCodec<Listing> {
Listing out = new Listing();
// for each field, get the value from the encoded object and set it in POJO
out.setId(document.getString(MongoFieldNames.DOCID));
out.setListingId(document.getLong(MongoFieldNames.LISTING_ID));
out.setTitle(document.getString(MongoFieldNames.LISTING_TITLE));
out.setUrl(document.getString(MongoFieldNames.LISTING_URL));
out.setSupportUrl(document.getString(MongoFieldNames.SUPPORT_PAGE_URL));
out.setHomepageUrl(document.getString(MongoFieldNames.HOME_PAGE_URL));
out.setTeaser(document.getString(MongoFieldNames.LISTING_TEASER));
out.setBody(document.getString(MongoFieldNames.LISTING_BODY));
out.setStatus(document.getString(MongoFieldNames.LISTING_STATUS));
out.setInstallsRecent(document.getLong(MongoFieldNames.RECENT_NSTALLS));
out.setInstallsTotal(document.getLong(MongoFieldNames.TOTAL_NSTALLS));
out.setLicense(document.getString(MongoFieldNames.LICENSE_TYPE));
out.setFavoriteCount(document.getLong(MongoFieldNames.MARKETPLACE_FAVORITES));
out.setFoundationMember(document.getBoolean(MongoFieldNames.FOUNDATION_MEMBER_FLAG));
out.setCategoryIds(document.getList(MongoFieldNames.CATEGORY_IDS, Integer.class));
out.setId(document.getString(DatabaseFieldNames.DOCID));
out.setTitle(document.getString(DatabaseFieldNames.LISTING_TITLE));
out.setUrl(document.getString(DatabaseFieldNames.URL));
out.setSupportUrl(document.getString(DatabaseFieldNames.SUPPORT_PAGE_URL));
out.setHomepageUrl(document.getString(DatabaseFieldNames.HOME_PAGE_URL));
out.setTeaser(document.getString(DatabaseFieldNames.LISTING_TEASER));
out.setBody(document.getString(DatabaseFieldNames.LISTING_BODY));
out.setStatus(document.getString(DatabaseFieldNames.LISTING_STATUS));
out.setInstallsRecent(document.getLong(DatabaseFieldNames.RECENT_NSTALLS));
out.setInstallsTotal(document.getLong(DatabaseFieldNames.TOTAL_NSTALLS));
out.setLicense(document.getString(DatabaseFieldNames.LICENSE_TYPE));
out.setFavoriteCount(document.getLong(DatabaseFieldNames.MARKETPLACE_FAVORITES));
out.setFoundationMember(document.getBoolean(DatabaseFieldNames.FOUNDATION_MEMBER_FLAG));
out.setCategoryIds(document.getList(DatabaseFieldNames.CATEGORY_IDS, String.class));
// for nested document types, use the converters to safely transform into POJO
out.setAuthors(document.getList(MongoFieldNames.LISTING_AUTHORS, Document.class).stream()
out.setAuthors(document.getList(DatabaseFieldNames.LISTING_AUTHORS, Document.class).stream()
.map(authorConverter::convert).collect(Collectors.toList()));
out.setOrganizations(document.getList(MongoFieldNames.LISTING_ORGANIZATIONS, Document.class).stream()
out.setOrganizations(document.getList(DatabaseFieldNames.LISTING_ORGANIZATIONS, Document.class).stream()
.map(organizationConverter::convert).collect(Collectors.toList()));
out.setTags(document.getList(MongoFieldNames.LISTING_TAGS, Document.class).stream().map(tagConverter::convert)
out.setTags(document.getList(DatabaseFieldNames.LISTING_TAGS, Document.class).stream().map(tagConverter::convert)
.collect(Collectors.toList()));
out.setVersions(document.getList(MongoFieldNames.LISTING_VERSIONS, Document.class).stream()
out.setVersions(document.getList(DatabaseFieldNames.LISTING_VERSIONS, Document.class).stream()
.map(versionConverter::convert).collect(Collectors.toList()));
out.setCategories(document.getList(MongoFieldNames.LISTING_CATEGORIES, Document.class).stream()
out.setCategories(document.getList(DatabaseFieldNames.LISTING_CATEGORIES, Document.class).stream()
.map(categoryConverter::convert).collect(Collectors.toList()));
// convert date to epoch milli
out.setCreationDate(document.getDate(MongoFieldNames.CREATION_DATE).toInstant().toEpochMilli());
out.setUpdateDate(document.getDate(MongoFieldNames.UPDATE_DATE).toInstant().toEpochMilli());
out.setCreationDate(document.getDate(DatabaseFieldNames.CREATION_DATE).toInstant().toEpochMilli());
out.setUpdateDate(document.getDate(DatabaseFieldNames.UPDATE_DATE).toInstant().toEpochMilli());
return out;
}
......
/* 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.Market;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
import com.mongodb.MongoClient;
/**
* MongoDB codec for transcoding of {@link Market} and {@link Document}
* objects. Used when writing or retrieving objects of given type from the
* database.
*
* @author Martin Lowe
*/
public class MarketCodec implements CollectibleCodec<Market> {
private final Codec<Document> documentCodec;
/**
* Creates the codec and initializes the codecs and converters needed to create
* a listing from end to end.
*/
public MarketCodec() {
this.documentCodec = MongoClient.getDefaultCodecRegistry().get(Document.class);
}
@Override
public void encode(BsonWriter writer, Market value, EncoderContext encoderContext) {
Document doc = new Document();
doc.put(DatabaseFieldNames.DOCID, value.getId());
doc.put(DatabaseFieldNames.URL, value.getUrl());
doc.put(DatabaseFieldNames.MARKET_NAME, value.getName());
doc.put(DatabaseFieldNames.CATEGORY_IDS, value.getCategoryIds());
documentCodec.encode(writer, doc, encoderContext);
}
@Override
public Class<Market> getEncoderClass() {
return Market.class;
}
@Override
public Market decode(BsonReader reader, DecoderContext decoderContext) {
Document document = documentCodec.decode(reader, decoderContext);
Market out = new Market();
out.setId(document.getString(DatabaseFieldNames.DOCID));
out.setUrl(document.getString(DatabaseFieldNames.URL));
out.setName(document.getString(DatabaseFieldNames.MARKET_NAME));
return out;
}
@Override
public Market generateIdIfAbsentFromDocument(Market document) {
if (!documentHasId(document)) {
document.setId(UUID.randomUUID().toString());
}
return document;
}
@Override
public boolean documentHasId(Market document) {
return StringUtils.isNotBlank(document.getId());
}
@Override
public BsonValue getDocumentId(Market document) {
return new BsonString(document.getId());
}
}
......@@ -8,7 +8,7 @@ package org.eclipsefoundation.marketplace.dto.converters;
import org.bson.Document;
import org.eclipsefoundation.marketplace.dto.Category;
import org.eclipsefoundation.marketplace.namespace.MongoFieldNames;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
/**
* @author martin
......@@ -19,20 +19,18 @@ public class CategoryConverter implements Converter<Category> {
@Override
public Category convert(Document src) {
Category out = new Category();
out.setId(src.getInteger(MongoFieldNames.DOCID));
out.setName(src.getString(MongoFieldNames.CATEGORY_NAME));
out.setUrl(src.getString(MongoFieldNames.CATEGORY_URL));
out.setMarketIds(src.getList(MongoFieldNames.MARKET_IDS, Integer.class));
out.setId(src.getString(DatabaseFieldNames.DOCID));
out.setName(src.getString(DatabaseFieldNames.CATEGORY_NAME));
out.setUrl(src.getString(DatabaseFieldNames.CATEGORY_URL));
return out;
}
@Override
public Document convert(Category src) {
Document doc = new Document();
doc.put(MongoFieldNames.DOCID, src.getId());
doc.put(MongoFieldNames.CATEGORY_NAME, src.getName());
doc.put(MongoFieldNames.CATEGORY_URL, src.getUrl());
doc.put(MongoFieldNames.MARKET_IDS, src.getMarketIds());
doc.put(DatabaseFieldNames.DOCID, src.getId());
doc.put(DatabaseFieldNames.CATEGORY_NAME, src.getName());
doc.put(DatabaseFieldNames.CATEGORY_URL, src.getUrl());
return doc;
}
......
......@@ -30,10 +30,7 @@ public class CatalogFilter implements DtoFilter<Catalog> {
@Override
public List<Bson> getFilters(RequestWrapper qps) {
List<Bson> filters = new ArrayList<>();
return filters;
return Collections.emptyList();
}
@Override
......
......@@ -15,8 +15,8 @@ import javax.enterprise.context.ApplicationScoped;
import org.bson.conversions.Bson;
import org.eclipsefoundation.marketplace.dto.Listing;
import org.eclipsefoundation.marketplace.model.RequestWrapper;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
import org.eclipsefoundation.marketplace.namespace.DtoTableNames;
import org.eclipsefoundation.marketplace.namespace.MongoFieldNames;
import org.eclipsefoundation.marketplace.namespace.UrlParameterNames;
import com.mongodb.client.model.Aggregates;
......@@ -35,49 +35,53 @@ import com.mongodb.client.model.Filters;
* <li>tags
* </ul>
*
* <p>
* Injects categories into the results by way of aggregate pipeline.
* </p>
*
* @author Martin Lowe
*/
@ApplicationScoped
public class ListingFilter implements DtoFilter<Listing> {
@Override
public List<Bson> getFilters(RequestWrapper qps) {
public List<Bson> getFilters(RequestWrapper wrap) {
List<Bson> filters = new ArrayList<>();
// Listing ID check
Optional<String> id = qps.getFirstParam(MongoFieldNames.LISTING_ID);
Optional<String> id = wrap.getFirstParam(UrlParameterNames.ID);
if (id.isPresent()) {
filters.add(Filters.eq(MongoFieldNames.LISTING_ID, Long.valueOf(id.get())));
filters.add(Filters.eq(DatabaseFieldNames.DOCID, id.get()));
}
// select by multiple IDs
List<String> ids = qps.getParams(UrlParameterNames.IDS);
List<String> ids = wrap.getParams(UrlParameterNames.IDS);
if (!ids.isEmpty()) {
filters.add(Filters.in(MongoFieldNames.LISTING_ID, ids));
filters.add(Filters.in(DatabaseFieldNames.DOCID, ids));
}
// Listing license type check
Optional<String> licType = qps.getFirstParam(MongoFieldNames.LICENSE_TYPE);
Optional<String> licType = wrap.getFirstParam(DatabaseFieldNames.LICENSE_TYPE);
if (licType.isPresent()) {
filters.add(Filters.eq(MongoFieldNames.LICENSE_TYPE, licType.get()));
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 = qps.getFirstParam(UrlParameterNames.OS);
Optional<String> os = wrap.getFirstParam(UrlParameterNames.OS);
if (os.isPresent()) {
versionFilters.add(Filters.eq("platforms", os.get()));
}
// solution version - eclipse version
Optional<String> eclipseVersion = qps.getFirstParam(UrlParameterNames.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 = qps.getFirstParam(UrlParameterNames.JAVA_VERSION);
Optional<String> javaVersion = wrap.getFirstParam(UrlParameterNames.JAVA_VERSION);
if (javaVersion.isPresent()) {
versionFilters.add(Filters.gte("min_java_version", javaVersion.get()));
}
......@@ -86,13 +90,13 @@ public class ListingFilter implements DtoFilter<Listing> {
}
// select by multiple tags
List<String> tags = qps.getParams(UrlParameterNames.TAGS);
List<String> tags = wrap.getParams(UrlParameterNames.TAGS);
if (!tags.isEmpty()) {
filters.add(Filters.in(MongoFieldNames.LISTING_TAGS + ".title", tags));
filters.add(Filters.in(DatabaseFieldNames.LISTING_TAGS + ".title", tags));
}
// text search
Optional<String> text = qps.getFirstParam(UrlParameterNames.QUERY_STRING);
Optional<String> text = wrap.getFirstParam(UrlParameterNames.QUERY_STRING);
if (text.isPresent()) {
filters.add(Filters.text(text.get()));
}
......@@ -103,16 +107,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.CATEGORY.getTableName(), MongoFieldNames.CATEGORY_IDS, "id",
"categories"));
List<String> marketIdsRaw = wrap.getParams(UrlParameterNames.MARKET_IDS);
List<Integer> marketIds = new ArrayList<>(marketIdsRaw.size());
try {
marketIdsRaw.forEach(s -> marketIds.add(Integer.valueOf(s)));
} catch (NumberFormatException e) {
// suppress
}
aggs.add(Aggregates.lookup(DtoTableNames.CATEGORY.getTableName(), DatabaseFieldNames.CATEGORY_IDS, DatabaseFieldNames.DOCID,
DatabaseFieldNames.LISTING_CATEGORIES));
List<String> marketIds = wrap.getParams(UrlParameterNames.MARKET_IDS);
if (!marketIds.isEmpty()) {
aggs.add(Aggregates.match(Filters.in("categories.market_ids", marketIds)));
}
......
/* 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 javax.enterprise.context.ApplicationScoped;
import org.bson.conversions.Bson;
import org.eclipsefoundation.marketplace.dto.Market;
import org.eclipsefoundation.marketplace.model.RequestWrapper;
import org.eclipsefoundation.marketplace.namespace.DatabaseFieldNames;
import org.eclipsefoundation.marketplace.namespace.DtoTableNames;
import com.mongodb.client.model.Aggregates;
/**
* Filter implementation for the {@linkplain Market} class.
*
* @author Martin Lowe
*/
@ApplicationScoped
public class MarketFilter implements DtoFilter<Market> {
@Override
public List<Bson> getFilters(RequestWrapper wrap) {
return Collections.emptyList();
}
@Override
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.CATEGORY.getTableName(), DatabaseFieldNames.CATEGORY_IDS, DatabaseFieldNames.DOCID,
"categories"));
return aggs;
}
@Override
public Class<Market> getType() {
return Market.class;
}
}
/* 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.Category;
import org.eclipsefoundation.marketplace.dto.Market;
import org.eclipsefoundation.marketplace.dto.codecs.CategoryCodec;
import org.eclipsefoundation.marketplace.dto.codecs.MarketCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides the {@link CategoryCodec} to MongoDB for conversions of
* {@link Category} objects.
*
* @author Martin Lowe
*/
public class MarketCodecProvider implements CodecProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(MarketCodecProvider.class);
@SuppressWarnings("unchecked")
@Override
public <T> Codec<T> get(Class<T> clazz, CodecRegistry registry) {
if (clazz == Market.class) {
LOGGER.debug("Registering custom Category class MongoDB codec");
return (Codec<T>) new MarketCodec();
}
return null;
}
}
......@@ -83,7 +83,6 @@ public class MongoQuery<T> {
setSort(sortVal.substring(0, idx), sortVal.substring(idx + 1), filters);
}
}
LOGGER.error("{}", filters);
if (!filters.isEmpty()) {
this.filter = Filters.and(filters);
}
......@@ -142,11 +141,8 @@ public class MongoQuery<T> {
List<Sortable<?>> fields = SortableHelper.getSortableFields(getDocType());
Optional<Sortable<?>> fieldContainer = SortableHelper.getSortableFieldByName(fields, sortField);
LOGGER.error("{}:{}", sortField, sortOrder);
if (fieldContainer.isPresent()) {
this.order = SortOrder.getOrderByName(sortOrder);
LOGGER.error("{}", order);
// add sorting query if the sortOrder matches a defined order
switch (order) {
case RANDOM:
......
......@@ -40,6 +40,7 @@ public class RequestWrapper {
private UriInfo uriInfo;
private HttpServletRequest request;
private UserAgent userAgent;
/**
* Generates a wrapper around the
......@@ -48,6 +49,7 @@ public class RequestWrapper {
RequestWrapper() {
this.uriInfo = ResteasyContext.getContextData(UriInfo.class);
this.request = ResteasyContext.getContextData(HttpServletRequest.class);
this.userAgent = null;
}
/**
......@@ -136,4 +138,15 @@ public class RequestWrapper {
public Object getAttribute(String key) {
return request.getAttribute(key);
}
public String getHeader(String key) {
return request.getHeader(key);
}
public UserAgent getUserAgent() {
if (userAgent == null) {
this.userAgent = new UserAgent(getHeader("user-agent"));
}
return this.userAgent;
}
}
/* 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 java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Splitter;
/**
* Custom User-Agent capture that handles and stores information based on MPC
* information.
*
* @author Martin Lowe
*/
public class UserAgent {
/**
* Matches a generic form of User-Agent strings with the following sections
*
* <code>Agent-Name/Agent-Version (System-Properties;) Platform (Platform-Details) Enhancements</code>
*
* As User-Agents aren't a standardized format, there is leniency on there being
* trailing sections being missing. The only required field is the Agent name
* and version, separated by a slash.
*/
private static final Pattern USER_AGENT_PATTERN = Pattern
.compile("^(\\S+\\/\\S+)\\s?(?:\\(([^\\)]*?)\\)([^\\(]+(?:\\(([^\\)]*?)\\)([^\\(]+)?)?)?)?$");
private static final String MPC_CLIENT_AGENT_NAME = "mpc";
private final String name;
private final String version;
private final String systemProperties;
private final String platform;
private final String platformDetails;
private final String enhancements;
private String javaVersion;
private String javaVendor;
private String os;
private String osVersion;
private String locale;
public UserAgent(String userAgent) {
Objects.requireNonNull(userAgent);
// check that the user agent matches the expected standard pattern
Matcher m = USER_AGENT_PATTERN.matcher(userAgent);
if (!m.matches()) {
throw new IllegalArgumentException("Passed string does not match an expected user-agent");
}
// get the name and version of the user agent
String agentDeclaration = m.group(0);
Iterator<String> it = Splitter.on('/').trimResults().split(agentDeclaration).iterator();
this.name = it.next();
this.version = it.next();
this.systemProperties = m.group(1);
this.platform = m.group(2);
this.platformDetails = m.group(3);
this.enhancements = m.group(4);
if (MPC_CLIENT_AGENT_NAME.equalsIgnoreCase(name)) {
handleMpc();
} else if (name.contains("bot")) {
// drop as we don't care about bot properties
} else {
handleWeb();
}
}
private void handleMpc() {
List<String> systemPropList = Splitter.on(';').splitToList(systemProperties);
if (systemPropList.size() != 3) {
// TODO throw exception?
}
// expected form example: Java <java version> <vendor>
String javaPropStr = systemPropList.get(0);
String javaPlatform = javaPropStr.substring(javaPropStr.indexOf(' ') + 1);
List<String> javaProps = Splitter.on(' ').limit(2).splitToList(javaPlatform);
this.javaVersion = javaProps.get(0);
this.javaVendor = javaProps.get(1);
// expected form: <OS name> <OS version> <??>
String systemPlatform = systemPropList.get(1);
this.locale = systemPropList.get(2);
}
private void handleWeb() {
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the version
*/
public String getVersion() {
return version;
}
/**
* @return the version
*/
public String getSystemProperties() {
return systemProperties;
}
/**
* @return the platform
*/
public String getPlatform() {
return platform;
}
/**
* @return the platformDetails
*/
public String getPlatformDetails() {
return platformDetails;
}
/**
* @return the enhancements
*/
public String getEnhancements() {
return enhancements;
}
/**
* @return the javaVersion
*/
public String getJavaVersion() {
return javaVersion;
}
/**
* @return the javaVendor
*/
public String getJavaVendor() {
return javaVendor;
}
/**
* @return the os
*/
public String getOs() {
return os;
}
/**
* @return the osVersion
*/
public String getOsVersion() {
return osVersion;
}
/**
* @return the locale
*/
public String getLocale() {
return locale;
}
}
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