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

org.finos.tracdap.gateway.proxy.rest.RestApiFields Maven / Gradle / Ivy

Go to download

TRAC D.A.P. gateway component, provides authentication, routing, load balancing and API translation

There is a newer version: 0.6.3
Show newest version
/*
 * Copyright 2022 Accenture Global Solutions 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 org.finos.tracdap.gateway.proxy.rest;

import org.finos.tracdap.common.exception.EStartup;
import com.google.protobuf.Descriptors;
import com.google.protobuf.Message;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.regex.Pattern;


public class RestApiFields {

    // For now, only support simple variables, e.g. /path/to/{request.field1}/{request.field2}
    // Captures of the form {request.field=some/path/*} require more work
    public static final Pattern SEGMENT_CAPTURE_PATTERN = Pattern.compile(
            "\\A\\{(?\\w+(?:\\.\\w+)*)}\\Z");

    public static boolean
    isSegmentCapture(String pathSegment) {

        return SEGMENT_CAPTURE_PATTERN.matcher(pathSegment).matches();
    }

    public static List
    prepareFieldsForPathSegment(Descriptors.Descriptor requestDescriptor, String pathSegment) {

        var segmentCapture = RestApiFields.SEGMENT_CAPTURE_PATTERN.matcher(pathSegment);

        if (!segmentCapture.matches())
            return List.of();

        var fullFieldName = segmentCapture.group("fieldName");

        return prepareFieldDescriptors(requestDescriptor, fullFieldName);
    }

    public static List
    prepareFieldDescriptors(Descriptors.Descriptor messageDescriptor, String fullFieldName) {

        // body = * means fold the body into the top level object
        // In this case, the sub-field selector should be an empty list
        if (fullFieldName.equals("*"))
            return List.of();

        var fieldNames = Arrays.asList(fullFieldName.split("\\."));
        var fieldDescriptors = new ArrayList();

        for (var fieldLevel = 0; fieldLevel < fieldNames.size(); fieldLevel++) {

            var fieldName = fieldNames.get(fieldLevel);
            var fieldDescriptor = messageDescriptor.findFieldByName(fieldName);

            if (fieldDescriptor == null) {
                // TODO: Error message
                var message = String.format("Invalid URL template for Rest API: Unknown request field [%s]", fieldName);
                throw new EStartup(message);
            }

            fieldDescriptors.add(fieldDescriptor);

            if (fieldLevel < fieldNames.size() - 1)
                messageDescriptor = fieldDescriptor.getMessageType();

            if (messageDescriptor == null) {
                // TODO: Error message
                var message = String.format("Invalid URL template for Rest API: Not a nested field [%s]", fieldName);
                throw new EStartup(message);
            }
        }

        return fieldDescriptors;
    }

    public static  Function
    prepareSubFieldMapper(List fields) {

        if (fields.size() == 1)
            return req -> req;

        return req -> mapSubfield(req, fields);
    }

    private static  Message.Builder
    mapSubfield(TRequest.Builder request, List fields) {

        for (var fieldLevel = 0; fieldLevel < fields.size() - 1; fieldLevel++) {

            var field = fields.get(fieldLevel);
            var subField = request.getFieldBuilder(field);

            if (subField == null) {
                subField = request.newBuilderForField(field);
                request.setField(field, subField);
            }

            request = subField;
        }

        return request;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy