Skip to content

Commit

Permalink
Merge pull request #12480 from Avishka-Shamendra/swagger-content-search
Browse files Browse the repository at this point in the history
Search Enhancements Add API Definition Content Search
  • Loading branch information
Avishka-Shamendra authored Sep 19, 2024
2 parents 2acef47 + 3fa71ef commit 6c8a7b7
Show file tree
Hide file tree
Showing 27 changed files with 2,149 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.apimgt.api.model;

/**
* This model is used to represent the API defintion content search results.
*/
public class APIDefinitionContentSearchResult {

private String id;
private String name;
private String apiUuid;
private String apiName;
private String apiContext;
private String apiVersion;
private String apiProvider;
private String apiType;
private String associatedType;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getApiUuid() {
return apiUuid;
}

public void setApiUuid(String apiUuid) {
this.apiUuid = apiUuid;
}

public String getApiName() {
return apiName;
}

public void setApiName(String apiName) {
this.apiName = apiName;
}

public String getApiVersion() {
return apiVersion;
}

public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}

public String getApiProvider() {
return apiProvider;
}

public void setApiProvider(String apiProvider) {
this.apiProvider = apiProvider;
}

public String getApiType() {
return apiType;
}

public void setApiType(String apiType) {
this.apiType = apiType;
}

public String getAssociatedType() {
return associatedType;
}

public void setAssociatedType(String associatedType) {
this.associatedType = associatedType;
}

public String getApiContext() {
return apiContext;
}

public void setApiContext(String apiContext) {
this.apiContext = apiContext;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,7 @@ public static class AccessTokenConstants {
public static final String REST_METHOD = "REST_METHOD";

// GraphQL related constants
public static final String API_TYPE = "API_TYPE";
public static final String API_TYPE = "ApiType";
public static final String HTTP_VERB = "HTTP_VERB";
public static final String GRAPHQL_API = "GRAPHQL";
public static final String GRAPHQL_SUBSCRIPTION_REQUEST = "isGraphqlSubscriptionRequest";
Expand Down Expand Up @@ -1826,6 +1826,9 @@ private ConfigParameters() {
public static final String REGISTRY_RESOURCE_URL_PREFIX =
"/registry/resource/_system/governance/apimgt/applicationdata/provider/";

public static final String APPLICATION_DATA_RESOURCE_URL_PREFIX =
"/apimgt/applicationdata/provider/";

public enum RegistryResourceTypesForUI {
TAG_THUMBNAIL
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO;
import org.wso2.carbon.apimgt.api.dto.KeyManagerPermissionConfigurationDTO;
import org.wso2.carbon.apimgt.api.model.API;
import org.wso2.carbon.apimgt.api.model.APIDefinitionContentSearchResult;
import org.wso2.carbon.apimgt.api.model.APIIdentifier;
import org.wso2.carbon.apimgt.api.model.APIKey;
import org.wso2.carbon.apimgt.api.model.APIProduct;
Expand Down Expand Up @@ -117,6 +118,7 @@
import org.wso2.carbon.apimgt.impl.utils.APIVersionComparator;
import org.wso2.carbon.apimgt.impl.utils.ApplicationUtils;
import org.wso2.carbon.apimgt.impl.utils.ContentSearchResultNameComparator;
import org.wso2.carbon.apimgt.impl.utils.SimpleContentSearchResultNameComparator;
import org.wso2.carbon.apimgt.impl.utils.VHostUtils;
import org.wso2.carbon.apimgt.impl.workflow.ApplicationDeletionApprovalWorkflowExecutor;
import org.wso2.carbon.apimgt.impl.workflow.ApplicationRegistrationSimpleWorkflowExecutor;
Expand All @@ -137,6 +139,7 @@
import org.wso2.carbon.apimgt.persistence.dto.DocumentSearchContent;
import org.wso2.carbon.apimgt.persistence.dto.Organization;
import org.wso2.carbon.apimgt.persistence.dto.SearchContent;
import org.wso2.carbon.apimgt.persistence.dto.APIDefSearchContent;
import org.wso2.carbon.apimgt.persistence.dto.UserContext;
import org.wso2.carbon.apimgt.persistence.exceptions.APIPersistenceException;
import org.wso2.carbon.apimgt.persistence.exceptions.OASPersistenceException;
Expand Down Expand Up @@ -4160,6 +4163,7 @@ public Map<String, Object> searchPaginatedContent(String searchQuery, String org
Map<String, Object> result = new HashMap<String, Object>();
SortedSet<API> apiSet = new TreeSet<API>(new APINameComparator());
SortedSet<APIProduct> apiProductSet = new TreeSet<APIProduct>(new APIProductNameComparator());
List<APIDefinitionContentSearchResult> defSearchList = new ArrayList<>();
int totalLength = 0;

String userame = (userNameWithoutChange != null) ? userNameWithoutChange : username;
Expand Down Expand Up @@ -4187,23 +4191,36 @@ public Map<String, Object> searchPaginatedContent(String searchQuery, String org
docItem.getApiVersion()));
api.setUuid(docItem.getApiUUID());
docMap.put(doc, api);
} else if (item instanceof APIDefSearchContent) {
APIDefSearchContent definitionItem = (APIDefSearchContent) item;
APIDefinitionContentSearchResult apiDefSearchResult = new APIDefinitionContentSearchResult();
apiDefSearchResult.setId(definitionItem.getId());
apiDefSearchResult.setName(definitionItem.getName());
apiDefSearchResult.setApiUuid(definitionItem.getApiUUID());
apiDefSearchResult.setApiName(definitionItem.getApiName());
apiDefSearchResult.setApiContext(definitionItem.getApiContext());
apiDefSearchResult.setApiProvider(definitionItem.getApiProvider());
apiDefSearchResult.setApiVersion(definitionItem.getApiVersion());
apiDefSearchResult.setApiType(definitionItem.getApiType());
apiDefSearchResult.setAssociatedType(definitionItem.getAssociatedType()); //API or API product
defSearchList.add(apiDefSearchResult);
} else if ("API".equals(item.getType())) {
DevPortalSearchContent publiserAPI = (DevPortalSearchContent) item;
API api = new API(new APIIdentifier(publiserAPI.getProvider(), publiserAPI.getName(),
publiserAPI.getVersion()));
api.setUuid(publiserAPI.getId());
api.setContext(publiserAPI.getContext());
api.setContextTemplate(publiserAPI.getContext());
api.setStatus(publiserAPI.getStatus());
api.setBusinessOwner(publiserAPI.getBusinessOwner());
api.setBusinessOwnerEmail(publiserAPI.getBusinessOwnerEmail());
api.setTechnicalOwner(publiserAPI.getTechnicalOwner());
api.setTechnicalOwnerEmail(publiserAPI.getTechnicalOwnerEmail());
api.setMonetizationEnabled(publiserAPI.getMonetizationStatus());
api.setAdvertiseOnly(publiserAPI.getAdvertiseOnly());
api.setRating(APIUtil.getAverageRating(publiserAPI.getId()));
api.setDescription(publiserAPI.getDescription());
api.setType(publiserAPI.getTransportType());
DevPortalSearchContent publisherAPI = (DevPortalSearchContent) item;
API api = new API(new APIIdentifier(publisherAPI.getProvider(), publisherAPI.getName(),
publisherAPI.getVersion()));
api.setUuid(publisherAPI.getId());
api.setContext(publisherAPI.getContext());
api.setContextTemplate(publisherAPI.getContext());
api.setStatus(publisherAPI.getStatus());
api.setBusinessOwner(publisherAPI.getBusinessOwner());
api.setBusinessOwnerEmail(publisherAPI.getBusinessOwnerEmail());
api.setTechnicalOwner(publisherAPI.getTechnicalOwner());
api.setTechnicalOwnerEmail(publisherAPI.getTechnicalOwnerEmail());
api.setMonetizationEnabled(publisherAPI.getMonetizationStatus());
api.setAdvertiseOnly(publisherAPI.getAdvertiseOnly());
api.setRating(APIUtil.getAverageRating(publisherAPI.getId()));
api.setDescription(publisherAPI.getDescription());
api.setType(publisherAPI.getTransportType());
apiSet.add(api);
} else if ("APIProduct".equals(item.getType())) {
DevPortalSearchContent devAPIProduct = (DevPortalSearchContent) item;
Expand All @@ -4226,10 +4243,11 @@ public Map<String, Object> searchPaginatedContent(String searchQuery, String org
compoundResult.addAll(apiSet);
compoundResult.addAll(docMap.entrySet());
compoundResult.addAll(apiProductSet);
compoundResult.sort(new ContentSearchResultNameComparator());
compoundResult.addAll(defSearchList);
compoundResult.sort(new SimpleContentSearchResultNameComparator());
result.put("length", sResults.getTotalCount());
} else {
result.put("length", compoundResult.size());
result.put("length", 0);
}
} catch (APIPersistenceException e) {
throw new APIManagementException("Error while searching content ", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.wso2.carbon.apimgt.api.dto.EnvironmentPropertiesDTO;
import org.wso2.carbon.apimgt.api.dto.UserApplicationAPIUsage;
import org.wso2.carbon.apimgt.api.model.API;
import org.wso2.carbon.apimgt.api.model.APIDefinitionContentSearchResult;
import org.wso2.carbon.apimgt.api.model.APIIdentifier;
import org.wso2.carbon.apimgt.api.model.APIInfo;
import org.wso2.carbon.apimgt.api.model.APIProduct;
Expand Down Expand Up @@ -164,13 +165,15 @@
import org.wso2.carbon.apimgt.impl.utils.APIVersionStringComparator;
import org.wso2.carbon.apimgt.impl.utils.ContentSearchResultNameComparator;
import org.wso2.carbon.apimgt.impl.utils.LifeCycleUtils;
import org.wso2.carbon.apimgt.impl.utils.SimpleContentSearchResultNameComparator;
import org.wso2.carbon.apimgt.impl.workflow.APIStateWorkflowDTO;
import org.wso2.carbon.apimgt.impl.workflow.WorkflowConstants;
import org.wso2.carbon.apimgt.impl.workflow.WorkflowException;
import org.wso2.carbon.apimgt.impl.workflow.WorkflowExecutor;
import org.wso2.carbon.apimgt.impl.workflow.WorkflowExecutorFactory;
import org.wso2.carbon.apimgt.impl.workflow.WorkflowStatus;
import org.wso2.carbon.apimgt.impl.wsdl.WSDLProcessor;
import org.wso2.carbon.apimgt.persistence.dto.APIDefSearchContent;
import org.wso2.carbon.apimgt.persistence.dto.DocumentContent;
import org.wso2.carbon.apimgt.persistence.dto.DocumentSearchContent;
import org.wso2.carbon.apimgt.persistence.dto.DocumentSearchResult;
Expand Down Expand Up @@ -5594,6 +5597,7 @@ public Map<String, Object> searchPaginatedContent(String searchQuery, String org
Map<String, Object> result = new HashMap<String, Object>();
SortedSet<API> apiSet = new TreeSet<API>(new APINameComparator());
SortedSet<APIProduct> apiProductSet = new TreeSet<APIProduct>(new APIProductNameComparator());
List<APIDefinitionContentSearchResult> defSearchList = new ArrayList<>();

String userame = userNameWithoutChange;
Organization org = new Organization(organization);
Expand Down Expand Up @@ -5662,14 +5666,28 @@ public Map<String, Object> searchPaginatedContent(String searchQuery, String org
api.setUuid(docItem.getApiUUID());
productDocMap.put(doc, api);
}
} else if (item instanceof APIDefSearchContent) {
APIDefSearchContent definitionItem = (APIDefSearchContent) item;
APIDefinitionContentSearchResult apiDefSearchResult = new APIDefinitionContentSearchResult();
apiDefSearchResult.setId(definitionItem.getId());
apiDefSearchResult.setName(definitionItem.getName());
apiDefSearchResult.setApiUuid(definitionItem.getApiUUID());
apiDefSearchResult.setApiName(definitionItem.getApiName());
apiDefSearchResult.setApiContext(definitionItem.getApiContext());
apiDefSearchResult.setApiProvider(definitionItem.getApiProvider());
apiDefSearchResult.setApiVersion(definitionItem.getApiVersion());
apiDefSearchResult.setApiType(definitionItem.getApiType());
apiDefSearchResult.setAssociatedType(definitionItem.getAssociatedType()); //API or API product
defSearchList.add(apiDefSearchResult);
}
}
compoundResult.addAll(apiSet);
compoundResult.addAll(apiProductSet);
compoundResult.addAll(docMap.entrySet());
compoundResult.addAll(productDocMap.entrySet());
compoundResult.sort(new ContentSearchResultNameComparator());
result.put("length", results.getTotalCount() );
compoundResult.addAll(defSearchList);
compoundResult.sort(new SimpleContentSearchResultNameComparator());
result.put("length", results.getTotalCount());
} else {
result.put("length", compoundResult.size() );
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.apimgt.impl.indexing.indexer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.common.SolrException;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.utils.IndexerUtil;
import org.wso2.carbon.governance.api.util.GovernanceUtils;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.RegistryConstants;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.registry.indexing.AsyncIndexer;
import org.wso2.carbon.registry.indexing.IndexingManager;
import org.wso2.carbon.registry.indexing.solr.IndexDocument;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
* This is the graphql definition indexer introduced to .graphgl definition artifacts for unified content search.
*/
public class GraphQLAPIDefinitionIndexer extends PlainTextIndexer {
public static final Log log = LogFactory.getLog(GraphQLAPIDefinitionIndexer.class);

@Override
public IndexDocument getIndexedDocument(AsyncIndexer.File2Index fileData) throws SolrException, RegistryException {
Registry registry = GovernanceUtils
.getGovernanceSystemRegistry(IndexingManager.getInstance().getRegistry(fileData.tenantId));
String definitionResourcePath =
fileData.path.substring(RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH.length());

// If the file is not a graphql definition file in provider path do not index
if (!definitionResourcePath.contains(APIConstants.APPLICATION_DATA_RESOURCE_URL_PREFIX)
|| !definitionResourcePath.contains(APIConstants.GRAPHQL_SCHEMA_FILE_EXTENSION)) {
return null;
}

// Extract only required info (types) from graphql definition to index
String schemaString = RegistryUtils.decodeBytes(fileData.data);
String definitionString = IndexerUtil.getTypesFromGraphQLSchemaString(schemaString);
fileData.data = definitionString.getBytes();

IndexDocument indexDocument = super.getIndexedDocument(fileData);
IndexDocument newIndexDocument = indexDocument;

if (log.isDebugEnabled()) {
log.debug("Executing GraphQL file indexer for resource at " + definitionResourcePath);
}

Resource definitionResource = null;
Map<String, List<String>> fields = indexDocument.getFields();

if (registry.resourceExists(definitionResourcePath)) {
definitionResource = registry.get(definitionResourcePath);
}

if (definitionResource != null) {
try {
IndexerUtil.fetchRequiredDetailsFromAssociatedAPI(registry, definitionResource, fields);
newIndexDocument =
new IndexDocument(fileData.path, null,
indexDocument.getRawContent(), indexDocument.getTenantId());
fields.put(APIConstants.DOCUMENT_INDEXER_INDICATOR, Arrays.asList("true"));
newIndexDocument.setFields(fields);
} catch (APIManagementException e) {
//error occurred while fetching details from API, but continuing indexing
log.error("Error while updating indexed document.", e);
}
}

return newIndexDocument;
}
}
Loading

0 comments on commit 6c8a7b7

Please sign in to comment.