From 5e47e958f4af851772b2e16ae26652d0b56743ac Mon Sep 17 00:00:00 2001 From: thomas loubrieu Date: Thu, 3 Jun 2021 17:18:53 -0700 Subject: [PATCH] add new file, forgot previously --- .../business/ProductBusinessObject.java | 277 ++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 src/main/java/gov/nasa/pds/api/engineering/elasticsearch/business/ProductBusinessObject.java diff --git a/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/business/ProductBusinessObject.java b/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/business/ProductBusinessObject.java new file mode 100644 index 0000000..d35c03d --- /dev/null +++ b/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/business/ProductBusinessObject.java @@ -0,0 +1,277 @@ +package gov.nasa.pds.api.engineering.elasticsearch.business; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.search.SearchHit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.Nullable; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +import gov.nasa.pds.api.engineering.controllers.MyProductsApiBareController; +import gov.nasa.pds.api.engineering.elasticsearch.ElasticSearchRegistryConnection; +import gov.nasa.pds.api.engineering.elasticsearch.ElasticSearchRegistrySearchRequestBuilder; +import gov.nasa.pds.api.engineering.elasticsearch.ElasticSearchUtil; +import gov.nasa.pds.api.engineering.elasticsearch.entities.EntityProduct; +import gov.nasa.pds.api.engineering.elasticsearch.entities.EntitytProductWithBlob; +import gov.nasa.pds.api.engineering.exceptions.UnsupportedElasticSearchProperty; +import gov.nasa.pds.api.model.ProductWithXmlLabel; +import gov.nasa.pds.model.Product; +import gov.nasa.pds.model.PropertyValues; + + +public class ProductBusinessObject { + + private static final Logger log = LoggerFactory.getLogger(ProductBusinessObject.class); + + private static final String DEFAULT_NULL_VALUE = null; + + private ElasticSearchRegistryConnection elasticSearchConnection; + private ElasticSearchRegistrySearchRequestBuilder searchRequestBuilder; + private ObjectMapper objectMapper; + + static final String LIDVID_SEPARATOR = "::"; + + public ProductBusinessObject(ElasticSearchRegistryConnection esRegistryConnection) { + this.elasticSearchConnection = esRegistryConnection; + + this.searchRequestBuilder = new ElasticSearchRegistrySearchRequestBuilder( + this.elasticSearchConnection.getRegistryIndex(), + this.elasticSearchConnection.getRegistryRefIndex(), + this.elasticSearchConnection.getTimeOutSeconds()); + + this.objectMapper = new ObjectMapper(); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + } + + + public String getLatestLidVidFromLid(String lid) throws IOException { + /* + * if lid is a lidvid then it return the same lidvid if available in the elasticsearch database + */ + + + lid = !(lid.contains(LIDVID_SEPARATOR))?lid+LIDVID_SEPARATOR:lid; + SearchRequest searchRequest = this.searchRequestBuilder.getSearchProductRequestHasLidVidPrefix(lid); + + SearchResponse searchResponse = this.elasticSearchConnection.getRestHighLevelClient().search(searchRequest, + RequestOptions.DEFAULT); + + if (searchResponse != null) { + + ArrayList lidvids = new ArrayList(); + String lidvid; + for (SearchHit searchHit : searchResponse.getHits()) { + lidvid = (String)searchHit.getSourceAsMap().get("lidvid");; + lidvids.add(lidvid); + } + + Collections.sort(lidvids); + + if (lidvids.size() == 0) return lid; + else return lidvids.get(lidvids.size() - 1); + + } + else { + return null; + } + + } + + + private static PropertyValues object2PropertyValue(Object o) { + PropertyValues pv = new PropertyValues(); + + if (o instanceof List) { + for (Object p : (List) o) { + pv.addValuesItem(String.valueOf(p)); + } + + } + else { + // TODO find a type which make String castable in PropertyValue, + // currently I am desperate so I transform String in a List + pv.addValuesItem(String.valueOf(o)); + } + + return pv; + + } + + + /** + * @param sourceAsMap source map coming from elasticSearch + * @param included_fields + * @param excluded_fields is ignored is included_fields is not null and not empty + * @return + */ + public static Map getFilteredProperties( + Map sourceAsMap, + List included_fields, + List excluded_fields){ + + Map filteredMapJsonProperties = new HashMap(); + + if ((included_fields == null) || (included_fields.size() ==0)) { + + String apiProperty; + for (Map.Entry entry : sourceAsMap.entrySet()) { + try { + apiProperty = ElasticSearchUtil.elasticPropertyToJsonProperty(entry.getKey()); + if ((excluded_fields == null) + || (! excluded_fields.contains(apiProperty))) + filteredMapJsonProperties.put( + apiProperty, + ProductBusinessObject.object2PropertyValue(entry.getValue()) + ); + } catch (UnsupportedElasticSearchProperty e) { + log.warn("ElasticSearch property " + entry.getKey() + " is not supported, ignored"); + } + } + + } + else { + + for (String field : included_fields) { + + + if (sourceAsMap.containsKey(ElasticSearchUtil.jsonPropertyToElasticProperty(field))) { + filteredMapJsonProperties.put( + field, + ProductBusinessObject.object2PropertyValue(sourceAsMap.get(field)) + ); + } + else { + filteredMapJsonProperties.put( + field, + ProductBusinessObject.object2PropertyValue(ProductBusinessObject.DEFAULT_NULL_VALUE) + ); + } + + } + + } + + + return filteredMapJsonProperties; + + + } + + + public Product getProduct(String lidvid) throws IOException { + return this.getProduct(lidvid, null); + } + + + public Product getProduct(String lidvid, @Nullable List fields) throws IOException { + GetRequest getProductRequest = this.searchRequestBuilder.getGetProductRequest(lidvid, false); + + GetResponse getResponse = null; + + + RestHighLevelClient restHighLevelClient = this.elasticSearchConnection.getRestHighLevelClient(); + + getResponse = restHighLevelClient.get( + getProductRequest, + RequestOptions.DEFAULT + ); + + if (getResponse.isExists()) { + log.info("get response " + getResponse.toString()); + Map sourceAsMap = getResponse.getSourceAsMap(); + Map filteredMapJsonProperties = + ProductBusinessObject.getFilteredProperties(sourceAsMap, fields, null); + + EntityProduct entityProduct; + + entityProduct = this.objectMapper.convertValue(sourceAsMap, EntityProduct.class); + + Product product = ElasticSearchUtil.ESentityProductToAPIProduct(entityProduct); + + product.setProperties(filteredMapJsonProperties); + + return product; + + } + else { + return null; + } + } + + + public ProductWithXmlLabel getProductWithXml(String lidvid) throws IOException { + return this.getProductWithXml(lidvid, null); + } + + // TODO make the method more generic by having the name of the class we want to cast the object into instead of a boolean, the code will be more neat also + public ProductWithXmlLabel getProductWithXml(String lidvid, @Nullable List field) throws IOException { + + GetRequest getProductRequest = this.searchRequestBuilder.getGetProductRequest(lidvid, true); + + GetResponse getResponse = null; + + + RestHighLevelClient restHighLevelClient = this.elasticSearchConnection.getRestHighLevelClient(); + + getResponse = restHighLevelClient.get( + getProductRequest, + RequestOptions.DEFAULT + ); + + if (getResponse.isExists()) { + log.info("get response " + getResponse.toString()); + Map sourceAsMap = getResponse.getSourceAsMap(); + + try { + + Map filteredMapJsonProperties = + ProductBusinessObject.getFilteredProperties( + sourceAsMap, + null, + new ArrayList(Arrays.asList(ElasticSearchUtil.elasticPropertyToJsonProperty(EntitytProductWithBlob.BLOB_PROPERTY))) + ); + + EntitytProductWithBlob entityProduct; + + entityProduct = this.objectMapper.convertValue(sourceAsMap, EntitytProductWithBlob.class); + + ProductWithXmlLabel product = ElasticSearchUtil.ESentityProductToAPIProduct(entityProduct); + product.setProperties(filteredMapJsonProperties); + + return product; + + } + catch (UnsupportedElasticSearchProperty e) { + log.error("This should never happen " + e.getMessage()); + return null; + } + + + + } + else { + return null; + } + + + + } +}