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

io.apicurio.datamodels.validation.rules.invalid.name.OasIdenticalPathTemplateRule Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2019 Red Hat
 *
 * 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 io.apicurio.datamodels.validation.rules.invalid.name;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.apicurio.datamodels.models.openapi.OpenApiPaths;
import io.apicurio.datamodels.validation.ValidationRuleMetaData;

/**
 * Implements the Identical Path Template Rule.
 * @author [email protected]
 */
public class OasIdenticalPathTemplateRule extends OasInvalidPropertyNameRule {

    Map> indexedPathTemplates = new HashMap<>();

    /**
     * Constructor.
     * @param ruleInfo
     */
    public OasIdenticalPathTemplateRule(ValidationRuleMetaData ruleInfo) {
        super(ruleInfo);
    }

    /**
     * Utility function to find other paths that are semantically similar to the path that is being checked against.
     * Two paths that differ only in formal parameter name are considered identical.
     * For example, paths /test/{var1} and /test/{var2} are identical.
     * See OAS 3 Specification's Path Templates section for more details.
     *
     * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#path-templating-matching
     *
     * @param pathToCheck
     * @param pathIndex
     */
    private List findIdenticalPaths(String pathToCheck) {
        List identicalPaths = new ArrayList<>();
        List pathSegments = indexedPathTemplates.get(pathToCheck);
        for (String checkAgainst : indexedPathTemplates.keySet()) {
            if (equals(checkAgainst, pathToCheck)) { continue; }
            boolean segmentsIdentical = true;
            List pathSegmentsToCheckAgainst = indexedPathTemplates.get(checkAgainst);
            if (pathSegments.size() != pathSegmentsToCheckAgainst.size()) {
                segmentsIdentical = false;
            } else {
                int idx = 0;
                for (PathSegment pathSegment : pathSegments) {
                    segmentsIdentical = segmentsIdentical && this.isSegmentIdentical(pathSegment, pathSegmentsToCheckAgainst.get(idx));
                    idx++;
                }
            }
            if (segmentsIdentical) {
                identicalPaths.add(checkAgainst);
            }
        }
        return identicalPaths;
    }

    /**
     * Utility function to test the equality of two path segments.
     * Segments are considered equal if they have same prefixes (if any) and same "normalized name".
     *
     * @param segment1
     * @param segment2
     * @return {boolean}
     */
    private boolean isSegmentIdentical(PathSegment segment1, PathSegment segment2) {
        if (equals(segment1.prefix, segment2.prefix)) {
            if (!hasValue(segment1.normalizedName) && !hasValue(segment2.normalizedName))
            {
                return true;
            }
            if ( (!hasValue(segment1.normalizedName) && hasValue(segment2.normalizedName)) ||
                    (hasValue(segment1.normalizedName) && !hasValue(segment2.normalizedName)) )
            {
                return false;
            }
            return equals(segment1.normalizedName, segment2.normalizedName);
        }
        return false;
    }

    @Override
    public void visitPaths(OpenApiPaths node) {
        // First index the path items.
        node.getItemNames().forEach(pathTemplate -> {
            if (isPathWellFormed(pathTemplate)) {
                List pathSegments = getPathSegments(pathTemplate);
                indexedPathTemplates.put(pathTemplate, pathSegments);
            }
        });

        node.getItemNames().forEach(pathTemplate -> {
            if (isPathWellFormed(pathTemplate)) {
                List identicalPaths = findIdenticalPaths(pathTemplate);
                if (identicalPaths.size() > 0) {
                    this.reportPathError(node.getItem(pathTemplate), map("path", pathTemplate));
                }
            }
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy