All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.elefana.api.ApiRouter Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright 2018 Viridian Software Limited
 *
 * Licensed 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 com.elefana.api;

import java.net.URLDecoder;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.elefana.api.document.IndexOpType;
import com.elefana.api.exception.ElefanaException;
import com.elefana.api.exception.NoSuchApiException;
import com.elefana.api.exception.ShardFailedException;
import com.elefana.cluster.ClusterService;
import com.elefana.document.BulkIngestService;
import com.elefana.document.DocumentService;
import com.elefana.indices.IndexFieldMappingService;
import com.elefana.indices.IndexTemplateService;
import com.elefana.node.NodesService;
import com.elefana.search.SearchService;

import io.netty.handler.codec.http.HttpMethod;

/**
 *
 */
@Service
public class ApiRouter {
	private static final Logger LOGGER = LoggerFactory.getLogger(ApiRouter.class);

	@Autowired
	private DocumentService documentService;
	@Autowired
	private BulkIngestService bulkIngestService;
	@Autowired
	private IndexFieldMappingService indexFieldMappingService;
	@Autowired
	private IndexTemplateService indexTemplateService;
	@Autowired
	private SearchService searchService;
	@Autowired
	private NodesService nodesService;
	@Autowired
	private ClusterService clusterService;

	public ApiRequest route(HttpMethod method, String url, String requestBody) throws ElefanaException {
		if (url.length() == 1) {
			return routeToRootUrl();
		}

		if(url.contains("?")) {
			url = url.substring(0, url.indexOf('?'));
		}
		final String[] urlComponents = url.startsWith("/") ? url.substring(1).split("\\/") : url.split("\\/");
		if (urlComponents[0] == null || urlComponents[0].isEmpty()) {
			return routeToRootUrl();
		}
		return routeToApi(method, url, urlComponents, requestBody);
	}

	private ApiRequest routeToRootUrl() throws ElefanaException {
		return clusterService.prepareClusterInfo();
	}

	private ApiRequest routeToApi(HttpMethod method, String url, String[] urlComponents, String requestBody)
			throws ElefanaException {
		switch (urlComponents[0].toLowerCase()) {
		case "_bulk":
			return routeToBulkApi(method, url, urlComponents, requestBody);
		case "_cluster":
			return routeToClusterApi(method, url, urlComponents, requestBody);
		case "_mapping":
			return routeToFieldMappingApi(method, url, urlComponents, requestBody);
		case "_mget":
			return routeToDocumentApi(method, url, urlComponents, requestBody);
		case "_msearch":
			return routeToSearchApi(method, url, urlComponents, requestBody);
		case "_nodes":
			return routeToNodeApi(method, url, urlComponents, requestBody);
		case "_search":
			return routeToSearchApi(method, url, urlComponents, requestBody);
		case "_template":
			return routeToIndexTemplateApi(method, url, urlComponents, requestBody);
		}

		switch (urlComponents.length) {
		case 2:
			switch (urlComponents[1].toLowerCase()) {
			case "_template":
				return routeToIndexTemplateApi(method, url, urlComponents, requestBody);
			case "_field_names":
			case "_field_caps":
			case "_mapping":
				return routeToFieldMappingApi(method, url, urlComponents, requestBody);
			case "_msearch":
			case "_search":
				return routeToSearchApi(method, url, urlComponents, requestBody);
			}
			break;
		case 3:
			switch (urlComponents[1].toLowerCase()) {
			case "_field_names":
			case "_mapping":
				return routeToFieldMappingApi(method, url, urlComponents, requestBody);
			}
			switch (urlComponents[2].toLowerCase()) {
			case "_msearch":
			case "_search":
				return routeToSearchApi(method, url, urlComponents, requestBody);
			}
			break;
		case 4:
			switch (urlComponents[1].toLowerCase()) {
			case "_mapping":
				switch (urlComponents[2].toLowerCase()) {
				case "field":
					return routeToFieldMappingApi(method, url, urlComponents, requestBody);
				}
			}
			break;
		case 5:
			switch (urlComponents[1].toLowerCase()) {
			case "_mapping":
				switch (urlComponents[3].toLowerCase()) {
				case "field":
					return routeToFieldMappingApi(method, url, urlComponents, requestBody);
				}
			}
			break;
		}

		if (isPutMethod(method)) {
			return routeToFieldMappingApi(method, url, urlComponents, requestBody);
		} else {
			return routeToDocumentApi(method, url, urlComponents, requestBody);
		}
	}

	private ApiRequest routeToBulkApi(HttpMethod method, String url, String[] urlComponents, String requestBody)
			throws ElefanaException {
		switch (urlComponents[0].toLowerCase()) {
		case "_bulk":
			return bulkIngestService.prepareBulkRequest(requestBody);
		}
		throw new NoSuchApiException(method, url);
	}

	private ApiRequest routeToClusterApi(HttpMethod method, String url, String[] urlComponents, String requestBody)
			throws ElefanaException {
		switch (urlComponents.length) {
		case 1:
			return clusterService.prepareClusterInfo();
		case 2: {
			final String target = urlDecode(urlComponents[1]);
			switch (target.toLowerCase()) {
			case "health":
				return clusterService.prepareClusterHealth();
			case "settings":
				return clusterService.prepareClusterSettings();
			}
			break;
		}
		case 3: {
			final String target = urlDecode(urlComponents[1]);
			switch (target.toLowerCase()) {
			case "health":
				return clusterService.prepareClusterHealth(urlComponents[2]);
			}
			break;
		}
		}
		throw new NoSuchApiException(method, url);
	}

	private ApiRequest routeToFieldMappingApi(HttpMethod method, String url, String[] urlComponents,
			String requestBody) throws ElefanaException {
		if (isGetMethod(method)) {
			switch (urlComponents.length) {
			case 1:
				// _mapping
				return indexFieldMappingService.prepareGetFieldMappings();
			case 2: {
				// INDICES/_mapping | INDICES/_field_caps | INDICES/_field_names
				final String indexPattern = urlDecode(urlComponents[0]);
				switch (urlComponents[1].toLowerCase()) {
				case "_field_names":
					return indexFieldMappingService.prepareGetFieldNames(indexPattern);
				case "_mapping":
					return indexFieldMappingService.prepareGetFieldMappings(indexPattern);
				case "_field_caps":
					return indexFieldMappingService.prepareGetFieldCapabilities(indexPattern);
				}
				break;
			}
			case 3: {
				// INDICES/_mapping/TYPE | INDICES/_field_names/TYPE
				final String indexPattern = urlDecode(urlComponents[0]);
				final String typePattern = urlDecode(urlComponents[2]);
				switch (urlComponents[1].toLowerCase()) {
				case "_field_names":
					return indexFieldMappingService.prepareGetFieldNames(indexPattern, typePattern);
				case "_mapping":
					return indexFieldMappingService.prepareGetFieldMappings(indexPattern, typePattern);
				}
				break;
			}
			case 4: {
				// e.g. INDICES/_mapping/field/FIELD
				final String indexPattern = urlDecode(urlComponents[0]);
				final String field = urlDecode(urlComponents[3]);
				switch (urlComponents[1].toLowerCase()) {
				case "_mapping":
					switch(urlComponents[2].toLowerCase()) {
					case "field":
						return indexFieldMappingService.prepareGetFieldMappings(indexPattern, "*", field);
					}
				}
				break;
			}
			case 5: {
				// e.g. INDICES/_mapping/TYPE/field/FIELD
				final String indexPattern = urlDecode(urlComponents[0]);
				final String typePattern = urlDecode(urlComponents[2]);
				final String field = urlDecode(urlComponents[4]);
				switch (urlComponents[1].toLowerCase()) {
				case "_mapping":
					switch(urlComponents[3].toLowerCase()) {
					case "field":
						return indexFieldMappingService.prepareGetFieldMappings(indexPattern, typePattern, field);
					}
				}
				break;
			}
			}
		} else if (isPostMethod(method)) {
			switch (urlComponents.length) {
			case 2: {
				// INDICES/_mapping or INDICES/_field_caps
				final String indexPattern = urlDecode(urlComponents[0]);
				switch (urlComponents[1].toLowerCase()) {
				case "_field_stats":
					return indexFieldMappingService.prepareGetFieldStats(indexPattern);
				case "_refresh":
					return indexFieldMappingService.prepareRefreshIndex(indexPattern);
				}
				break;
			}
			}
		} else if (isPutMethod(method)) {
			final String index = urlDecode(urlComponents[0]);
			return indexFieldMappingService.preparePutFieldMappings(index, requestBody);
		}
		throw new NoSuchApiException(method, url);
	}

	private ApiRequest routeToDocumentApi(HttpMethod method, String url, String[] urlComponents, String requestBody)
			throws ElefanaException {
		switch (urlComponents.length) {
		case 1:
			switch (urlComponents[0].toLowerCase()) {
			case "_mget":
				return documentService.prepareMultiGet(requestBody);
			default:
				final String index = urlDecode(urlComponents[0]);
				if(isDeleteMethod(method)) {
					return documentService.prepareDeleteIndex(index, "*");
				}
				break;
			}
			break;
		case 2: {
			// 0 = INDEX
			final String index = urlDecode(urlComponents[0]);

			switch (urlComponents[1].toLowerCase()) {
			case "_mget":
				return documentService.prepareMultiGet(index, requestBody);
			case "_mapping":
			case "_refresh":
			case "_field_stats":
				return routeToFieldMappingApi(method, url, urlComponents, requestBody);
			}
			final String type = urlDecode(urlComponents[1]);

			if (isPostMethod(method)) {
				return documentService
						.prepareIndex(index, type, UUID.randomUUID().toString(), requestBody, IndexOpType.OVERWRITE);
			} else if(isDeleteMethod(method)) {
				return documentService.prepareDeleteIndex(index, type);
			}
			break;
		}
		case 3: {
			// 0 = INDEX, 1 = TYPE
			final String index = urlDecode(urlComponents[0]);
			final String type = urlDecode(urlComponents[1]);
			
			switch (urlComponents[1].toLowerCase()) {
			case "_mapping":
				return routeToFieldMappingApi(method, url, urlComponents, requestBody);
			}

			switch (urlComponents[2].toLowerCase()) {
			case "_mget":
				return documentService.prepareMultiGet(index, type, requestBody);
			}
			final String id = urlDecode(urlComponents[2]);

			if (isGetMethod(method) || isHeadMethod(method)) {
				return documentService.prepareGet(index, type, id, isGetMethod(method));
			} else if (isPostMethod(method)) {
				return documentService.prepareIndex(index, type, id, requestBody, IndexOpType.OVERWRITE);
			} else if (isDeleteMethod(method)) {
				return documentService.prepareDelete(index, type, id);
			}
			break;
		}
		case 4: {
			// 0 = INDEX, 1 = TYPE, 2 = ID, 3 = OP
			final String index = urlDecode(urlComponents[0]);
			final String type = urlDecode(urlComponents[1]);
			final String id = urlDecode(urlComponents[2]);

			if (isPostMethod(method) || isPutMethod(method)) {
				switch (urlComponents[3].toLowerCase()) {
				case "_create": {
					return documentService.prepareIndex(index, type, id, requestBody,
							IndexOpType.CREATE);
				}
				case "_update": {
					return documentService.prepareIndex(index, type, id, requestBody,
							IndexOpType.UPDATE);
				}
				}
			}
			break;
		}
		case 5: {
			switch (urlComponents[1].toLowerCase()) {
			case "_mapping":
				return routeToFieldMappingApi(method, url, urlComponents, requestBody);
			}
			break;
		}
		}
		throw new NoSuchApiException(method, url);
	}

	private ApiRequest routeToSearchApi(HttpMethod method, String url, String[] urlComponents, String requestBody)
			throws ElefanaException {
		switch (urlComponents.length) {
		case 1:
			// _search
			switch (urlComponents[0].toLowerCase()) {
			case "_search":
				return searchService.prepareSearch(requestBody);
			case "_msearch":
				return searchService.prepareMultiSearch(requestBody);
			}
			break;
		case 2: {
			// INDICES/_search
			final String indexPattern = urlDecode(urlComponents[0]);
			switch (urlComponents[1].toLowerCase()) {
			case "_search":
				return searchService.prepareSearch(indexPattern, requestBody);
			case "_msearch":
				return searchService.prepareMultiSearch(indexPattern, requestBody);
			}
			break;
		}
		case 3:
			// INDICES/TYPES/_search
			final String indexPattern = urlDecode(urlComponents[0]);
			final String typePattern = urlDecode(urlComponents[1]);

			switch (urlComponents[2].toLowerCase()) {
			case "_search":
				return searchService.prepareSearch(indexPattern, typePattern, requestBody);
			case "_msearch":
				return searchService.prepareMultiSearch(indexPattern, typePattern, requestBody);
			}
			break;
		}
		throw new NoSuchApiException(method, url);
	}

	private ApiRequest routeToNodeApi(HttpMethod method, String url, String[] urlComponents, String requestBody)
			throws ElefanaException {
		switch (urlComponents.length) {
		case 1:
			return nodesService.prepareNodesInfo();
		case 2: {
			final String nodes = urlDecode(urlComponents[1]);
			switch (nodes.toLowerCase()) {
			case "_all":
				return nodesService.prepareNodesInfo();
			case "_local":
				return nodesService.prepareLocalNodeInfo();
			default:
				return nodesService.prepareNodesInfo(nodes.split(","));
			}
		}
		case 3: {
			final String nodes = urlDecode(urlComponents[1]);
			final String[] filter = urlComponents[2].split(",");
			switch (nodes.toLowerCase()) {
			case "_all":
				return nodesService.prepareNodesInfo(filter);
			case "_local":
				return nodesService.prepareLocalNodeInfo(filter);
			default:
				return nodesService.prepareNodesInfo(nodes.split(","), filter);
			}
		}
		}
		throw new NoSuchApiException(method, url);
	}

	private ApiRequest routeToIndexTemplateApi(HttpMethod method, String url, String[] urlComponents,
			String requestBody) throws ElefanaException {
		switch (urlComponents.length) {
		case 2:
			switch(urlComponents[0].toLowerCase()) {
			case "_template":
				final String templateId = urlDecode(urlComponents[1]);
				if (isGetMethod(method) || isHeadMethod(method)) {
					return indexTemplateService.prepareGetIndexTemplate(templateId, isGetMethod(method));
				} else if (isPostMethod(method) || isPutMethod(method)) {
					return indexTemplateService.preparePutIndexTemplate(templateId, requestBody);
				}
				break;
			default:
				//INDEX/_template
				return indexTemplateService.prepareGetIndexTemplateForIndex(urlComponents[0]);
			}
			break;
		}
		throw new NoSuchApiException(method, url);
	}

	private boolean isHeadMethod(HttpMethod method) {
		return method.equals(HttpMethod.HEAD);
	}

	private boolean isGetMethod(HttpMethod method) {
		return method.equals(HttpMethod.GET);
	}

	private boolean isPostMethod(HttpMethod method) {
		return method.equals(HttpMethod.POST);
	}

	private boolean isPutMethod(HttpMethod method) {
		return method.equals(HttpMethod.PUT);
	}

	private boolean isDeleteMethod(HttpMethod method) {
		return method.equals(HttpMethod.DELETE);
	}

	private String urlDecode(String url) throws ElefanaException {
		try {
			return URLDecoder.decode(url, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			throw new ShardFailedException();
		}
	}

	public DocumentService getDocumentApi() {
		return documentService;
	}

	public BulkIngestService getBulkApi() {
		return bulkIngestService;
	}

	public IndexFieldMappingService getFieldMappingApi() {
		return indexFieldMappingService;
	}

	public IndexTemplateService getIndexTemplateApi() {
		return indexTemplateService;
	}

	public SearchService getSearchApi() {
		return searchService;
	}

	public NodesService getNodeApi() {
		return nodesService;
	}

	public ClusterService getClusterApi() {
		return clusterService;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy