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

eu.cqse.check.framework.util.tokens.TokenPatternMatch Maven / Gradle / Ivy

Go to download

The Teamscale Custom Check API allows users to extend Teamscale by writing custom analyses that create findings.

There is a newer version: 2024.7.2
Show newest version
/*
 * Copyright (c) CQSE GmbH
 *
 * 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 eu.cqse.check.framework.util.tokens;

import java.util.ArrayList;
import java.util.List;

import org.conqat.lib.commons.collections.CollectionUtils;
import org.conqat.lib.commons.collections.ListMap;
import org.conqat.lib.commons.string.StringUtils;

import eu.cqse.check.framework.scanner.IToken;
import eu.cqse.check.framework.shallowparser.TokenStreamTextUtils;

/**
 * A single match created by a {@link TokenPattern}. Keeps track of any groups that have been
 * matched by parts of the pattern. A group is identified by an arbitrary integer. See also
 * {@link TokenPattern#group(int)}.
 * 
 * Multiple segments of the tokenStream can be associated with the same group. In this case,
 * {@link #getMatchGroup(int)} will return multiple {@link MatchGroupElement}s for the group.
 */
public class TokenPatternMatch {

	/** The token stream against which the matches were constructed. */
	private final List tokenStream;

	/**
	 * Maps from the group index to the ranges that are included in the group.
	 */
	private final ListMap groups = new ListMap<>();

	/** Constructor. */
	public TokenPatternMatch(List tokenStream) {
		this.tokenStream = tokenStream;
	}

	/**
	 * Appends the given tokens to the group with the given index if the given range contains at least
	 * one token.
	 */
	public void appendToGroup(Integer groupIndex, int inclusiveStartIndex, int exclusiveEndIndex) {
		if (inclusiveStartIndex < exclusiveEndIndex) {
			groups.add(groupIndex, new Range(inclusiveStartIndex, exclusiveEndIndex));
		}
	}

	/**
	 * Returns the text of the tokens in the given group. All {@link MatchGroupElement}s for the given
	 * group will be concatenated.
	 */
	public List groupTexts(int groupIndex) {
		return TokenStreamTextUtils.getTokenTexts(groupTokens(groupIndex));
	}

	/**
	 * Returns the indices into the token stream in the given group or an empty list. All
	 * {@link MatchGroupElement}s for the given group will be concatenated.
	 */
	public List groupIndices(int groupIndex) {
		List ranges = groups.getCollection(groupIndex);
		if (ranges == null) {
			return CollectionUtils.emptyList();
		}
		List indices = new ArrayList<>();
		for (Range range : ranges) {
			for (int i = range.inclusiveStartIndex; i < range.exclusiveEndIndex; i++) {
				indices.add(i);
			}
		}
		return indices;
	}

	/**
	 * Returns the tokens in the given group or an empty list. All {@link MatchGroupElement}s for the
	 * given group will be concatenated.
	 */
	public List groupTokens(int groupIndex) {
		List tokens = new ArrayList<>();
		for (Integer index : groupIndices(groupIndex)) {
			tokens.add(tokenStream.get(index));
		}
		return tokens;
	}

	/**
	 * Returns the TokenStream parts matched in this group. Each part is represented by a
	 * {@link MatchGroupElement} and can contain multiple {@link IToken}s, depending on the used
	 * pattern.
	 */
	public List getMatchGroup(int groupIndex) {
		List ranges = groups.getCollection(groupIndex);
		if (ranges == null) {
			return CollectionUtils.emptyList();
		}
		List groupElements = new ArrayList<>();
		for (Range range : ranges) {
			groupElements.add(
					new MatchGroupElement(tokenStream.subList(range.inclusiveStartIndex, range.exclusiveEndIndex)));
		}
		return groupElements;
	}

	/**
	 * Returns the concatenated text of the tokens in the given group. All {@link MatchGroupElement}s
	 * for the given group will be concatenated. If the group was not matched, returns the empty string.
	 */
	public String groupString(int groupIndex) {
		return StringUtils.concat(groupTexts(groupIndex), StringUtils.EMPTY_STRING);
	}

	/**
	 * Returns true if the match contains tokens in the given group.
	 */
	public boolean hasGroup(int groupIndex) {
		return groups.containsCollection(groupIndex);
	}

	/** Merges the group information from given match into this match. */
	public void mergeFrom(TokenPatternMatch other) {
		groups.addAll(other.groups);
	}

	/**
	 * Returns a list of all group strings in all matches of the group with the given index.
	 */
	public static List getAllStrings(List matches, int groupIndex) {
		List strings = new ArrayList<>();
		for (TokenPatternMatch match : matches) {
			strings.add(match.groupString(groupIndex));
		}
		return strings;
	}

	/**
	 * Returns a list of all group tokens in all matches of the group with the given index.
	 */
	public static List getAllTokens(List matches, int groupIndex) {
		List tokens = new ArrayList<>();
		for (TokenPatternMatch match : matches) {
			tokens.addAll(match.groupTokens(groupIndex));
		}
		return tokens;
	}

	/** A range of indices into a token stream. */
	private static class Range {

		/** The inclusive start index into the token stream. */
		private final int inclusiveStartIndex;

		/** The exclusive end index into the token stream. */
		private final int exclusiveEndIndex;

		/** Constructor. */
		public Range(int inclusiveStartIndex, int exclusiveEndIndex) {
			this.inclusiveStartIndex = inclusiveStartIndex;
			this.exclusiveEndIndex = exclusiveEndIndex;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy