Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MARP-947 re structure product module content in product #108

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@ private void createDetailResource(ProductDetailModel model, Product product) {
model.setContactUs(product.getContactUs());
model.setCost(product.getCost());
model.setInstallationCount(product.getInstallationCount());
model.setProductModuleContent(CollectionUtils.firstElement(product.getProductModuleContents()));
model.setProductModuleContent(product.getProductModuleContent());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public class EntityConstants {
public static final String FEEDBACK = "Feedback";
public static final String PRODUCT_CUSTOM_SORT = "ProductCustomSort";
public static final String PRODUCT_JSON_CONTENT = "ProductJsonContent";
public static final String PRODUCT_MODULE_CONTENT = "ProductModuleContent";
}
ntqdinh-axonivy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package com.axonivy.market.constants;

public class MongoDBConstants {

private MongoDBConstants() {
}

public static final String ID ="_id";
public static final String ADD_FIELD ="$addFields";
public static final String PRODUCT_MODULE_CONTENTS ="productModuleContents";
public static final String PRODUCT_MODULE_CONTENT ="productModuleContent";
public static final String PRODUCT_MODULE_CONTENT_QUERY ="$productModuleContents";
public static final String FILTER ="$filter";
public static final String INPUT ="input";
public static final String AS ="as";
public static final String CONDITION ="cond";
public static final String EQUAL ="$eq";
public static final String PRODUCT_MODULE_CONTENT_TAG ="$$productModuleContent.tag";
public static final String PRODUCT_COLLECTION ="Product";
public static final String NEWEST_RELEASED_VERSION_QUERY = "$newestReleaseVersion";
public static final String INSTALLATION_COUNT = "InstallationCount";
public static final String SYNCHRONIZED_INSTALLATION_COUNT ="SynchronizedInstallationCount";

}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public ResponseEntity<Integer> syncInstallationCount(
}

@GetMapping(BY_ID)
@Operation(summary = "increase installation count by 1", description = "update installation count when click download product files by users")
@Operation(summary = "get product detail by ID", description = "Return product detail by product id (from meta.json)")
public ResponseEntity<ProductDetailModel> findProductDetails(
@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "approval-decision-utils", in = ParameterIn.PATH) String id) {
var productDetail = productService.fetchProductDetail(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;

import java.io.Serial;
Expand Down Expand Up @@ -57,12 +58,12 @@ public class Product implements Serializable {
private int installationCount;
private Date newestPublishedDate;
private String newestReleaseVersion;
private List<ProductModuleContent> productModuleContents;
@Transient
private ProductModuleContent productModuleContent;
private List<MavenArtifact> artifacts;
private Boolean synchronizedInstallationCount;
private Integer customOrder;
private List<String> releasedVersions;

@Transient
private String metaProductJsonUrl;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,32 @@

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.io.Serial;
import java.io.Serializable;
import java.util.Map;

import static com.axonivy.market.constants.EntityConstants.PRODUCT_MODULE_CONTENT;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Document(PRODUCT_MODULE_CONTENT)
public class ProductModuleContent implements Serializable {
@Id
private String id;
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "product Id (from meta.json)", example = "portal")
private String productId;
@Schema(description = "Target release tag", example = "v10.0.25")
private String tag;
@Schema(description = "Product detail description content ", example = "{ \"de\": \"E-Sign-Konnektor\", \"en\": \"E-sign connector\" }")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ public ProductModuleContent getReadmeAndProductContentsFromTag(Product product,
ProductModuleContent productModuleContent = new ProductModuleContent();
try {
List<GHContent> contents = getProductFolderContents(product, ghRepository, tag);
productModuleContent.setProductId(product.getId());
productModuleContent.setTag(tag);
updateDependencyContentsFromProductJson(productModuleContent, contents , product);
List<GHContent> readmeFiles = contents.stream().filter(GHContent::isFile)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.axonivy.market.repository;

import com.axonivy.market.entity.ProductModuleContent;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ProductModuleContentRepository extends MongoRepository<ProductModuleContent, String> {
ProductModuleContent findByTagAndProductId(String tag, String productId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import com.axonivy.market.constants.MongoDBConstants;
import com.axonivy.market.entity.Product;
import com.axonivy.market.entity.ProductModuleContent;
import com.axonivy.market.repository.CustomProductRepository;
import org.bson.Document;
import com.axonivy.market.repository.ProductModuleContentRepository;
import lombok.Builder;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
Expand All @@ -13,61 +15,54 @@
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;


@Builder
public class CustomProductRepositoryImpl implements CustomProductRepository {
private final MongoTemplate mongoTemplate;
private final ProductModuleContentRepository contentRepository;

public CustomProductRepositoryImpl(MongoTemplate mongoTemplate) {
public CustomProductRepositoryImpl(MongoTemplate mongoTemplate, ProductModuleContentRepository contentRepository) {
this.mongoTemplate = mongoTemplate;
this.contentRepository = contentRepository;
}

private AggregationOperation createIdMatchOperation(String id) {
return Aggregation.match(Criteria.where(MongoDBConstants.ID).is(id));
}

public Document createDocumentFilterProductModuleContentByTag(String tag) {
Document isProductModuleContentOfCurrentTag = new Document(MongoDBConstants.EQUAL,
Arrays.asList(MongoDBConstants.PRODUCT_MODULE_CONTENT_TAG, tag));
Document loopOverProductModuleContents = new Document(MongoDBConstants.INPUT,
MongoDBConstants.PRODUCT_MODULE_CONTENT_QUERY)
.append(MongoDBConstants.AS, MongoDBConstants.PRODUCT_MODULE_CONTENT);
return loopOverProductModuleContents.append(MongoDBConstants.CONDITION, isProductModuleContentOfCurrentTag);
}

private AggregationOperation createReturnFirstModuleContentOperation() {
return context -> new Document(MongoDBConstants.ADD_FIELD,
new Document(MongoDBConstants.PRODUCT_MODULE_CONTENTS,
new Document(MongoDBConstants.FILTER, createDocumentFilterProductModuleContentByTag(MongoDBConstants.NEWEST_RELEASED_VERSION_QUERY))));
}

private AggregationOperation createReturnFirstMatchTagModuleContentOperation(String tag) {
return context -> new Document(MongoDBConstants.ADD_FIELD,
new Document(MongoDBConstants.PRODUCT_MODULE_CONTENTS,
new Document(MongoDBConstants.FILTER, createDocumentFilterProductModuleContentByTag(tag))));
}

public Product queryProductByAggregation(Aggregation aggregation) {
return Optional.of(mongoTemplate.aggregate(aggregation, MongoDBConstants.PRODUCT_COLLECTION, Product.class))
.map(AggregationResults::getUniqueMappedResult).orElse(null);
}

@Override
public Product getProductByIdAndTag(String id, String tag) {
// Create the aggregation pipeline
Aggregation aggregation = Aggregation.newAggregation(createIdMatchOperation(id), createReturnFirstMatchTagModuleContentOperation(tag));
Product result = findProductById(id);
if (!Objects.isNull(result)) {
ProductModuleContent content = contentRepository.findByTagAndProductId(tag,id);
result.setProductModuleContent(content);
}
return result;
}

private Product findProductById(String id) {
Aggregation aggregation = Aggregation.newAggregation(createIdMatchOperation(id));
return queryProductByAggregation(aggregation);
}

@Override
public Product getProductById(String id) {
Aggregation aggregation = Aggregation.newAggregation(createIdMatchOperation(id), createReturnFirstModuleContentOperation());
return queryProductByAggregation(aggregation);
Product result = findProductById(id);
if (!Objects.isNull(result)) {
ProductModuleContent content = contentRepository.findByTagAndProductId(
result.getNewestReleaseVersion(), id);
result.setProductModuleContent(content);
}
return result;
}

@Override
Expand All @@ -78,19 +73,17 @@ public List<String> getReleasedVersionsById(String id) {
return Collections.emptyList();
}
return product.getReleasedVersions();

}

public int updateInitialCount(String productId, int initialCount) {
Update update = new Update().inc("InstallationCount", initialCount).set("SynchronizedInstallationCount", true);
Update update = new Update().inc(MongoDBConstants.INSTALLATION_COUNT, initialCount).set(MongoDBConstants.SYNCHRONIZED_INSTALLATION_COUNT, true);
mongoTemplate.updateFirst(createQueryById(productId), update, Product.class);
return Optional.ofNullable(getProductById(productId)).map(Product::getInstallationCount).orElse(0);
}

@Override
public int increaseInstallationCount(String productId) {
Update update = new Update().inc("InstallationCount", 1);
// Find and modify the document, then return the updated InstallationCount field
Update update = new Update().inc(MongoDBConstants.INSTALLATION_COUNT, 1);
Product updatedProduct = mongoTemplate.findAndModify(createQueryById(productId), update,
FindAndModifyOptions.options().returnNew(true), Product.class);
return updatedProduct != null ? updatedProduct.getInstallationCount() : 0;
Expand Down
Loading
Loading