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

org.conqat.engine.commons.findings.location.TextRegionLocation Maven / Gradle / Ivy

/*
 * 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 org.conqat.engine.commons.findings.location;

import java.util.Objects;

import org.conqat.lib.commons.assertion.CCSMAssert;
import org.conqat.lib.commons.js_export.ExportToTypeScript;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

/**
 * This class denotes a region of text in an element.
 *
 * Context: Due to the way ConQAT deals with text, the class is a little
 * bit more complex than expected. First, in ConQAT all text is normalized to
 * use Unix style line endings (regardless of the line endings in the file).
 * Second, ConQAT may apply filters, i.e. the internal (filtered) text
 * representation may be different from the (raw) text in the file.
 * Additionally, a location is best described by character offsets into the
 * string, while a user typically expects line numbers. Conversion between all
 * these representations is easy, as long as ConQAT internal representation is
 * available. Without it, conversion is not possible.
 *
 * Rationale: When findings are reported to a user, the raw offsets
 * and/or lines should be used, as these are more meaningful (visible in other
 * editors as well). Also for persisting in a report, the raw positions are
 * preferred, as the filtered ones depend on the ConQAT configuration, while raw
 * offsets are independent of filter configuration. When working with findings
 * within ConQAT, typically the filtered positions are needed, as most
 * processors also work on the filtered representation. However, in such a case
 * the corresponding element is typically available and thus conversion to the
 * filtered representation is easy.
 *
 * Implementation: The finding (as well as the findings report) only
 * stores raw positions. While the offsets would be sufficient, we also store
 * line numbers to be able to provide meaningful user output. Filtered positions
 * are not stored, but are made available via utility methods in the resource
 * bundle. All fields are mandatory, i.e., it is not allowed to fill any
 * position entry with invalid data (contrary to the old CodeRegionLocation,
 * where -1 could be used to denote missing information).
 */
@ExportToTypeScript
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = TextRegionLocation.class)
public class TextRegionLocation extends ElementLocation {

	/**
	 * Version used for serialization.
	 */
	private static final long serialVersionUID = 1;

	/**
	 * An unknown offset used to indicate, that the line information is to be used
	 * to calculate character offset from.
	 */
	public static final int UNKNOWN_TEXT_REGION_OFFSET = -1;

	/**
	 * The name of the JSON property name for {@link #rawStartOffset}.
	 */
	private static final String RAW_START_OFFSET_PROPERTY = "rawStartOffset";

	/**
	 * The name of the JSON property name for {@link #rawEndOffset}.
	 */
	private static final String RAW_END_OFFSET_PROPERTY = "rawEndOffset";

	/**
	 * The name of the JSON property name for {@link #rawStartLine}.
	 */
	private static final String RAW_START_LINE_PROPERTY = "rawStartLine";

	/**
	 * The name of the JSON property name for {@link #rawEndLine}.
	 */
	private static final String RAW_END_LINE_PROPERTY = "rawEndLine";

	/**
	 * The absolute start position of the region in the (raw) text (zero based,
	 * inclusive).
	 */
	@JsonProperty(RAW_START_OFFSET_PROPERTY)
	private final int rawStartOffset;

	/**
	 * The absolute end position in the (raw) text (zero based, inclusive).
	 */
	@JsonProperty(RAW_END_OFFSET_PROPERTY)
	private final int rawEndOffset;

	/**
	 * The line corresponding to {@link #rawStartOffset} (one-based, inclusive).
	 */
	@JsonProperty(RAW_START_LINE_PROPERTY)
	private final int rawStartLine;

	/**
	 * The line corresponding to {@link #rawEndOffset} (one-based, inclusive).
	 */
	@JsonProperty(RAW_END_LINE_PROPERTY)
	private final int rawEndLine;

	/**
	 * Constructor.
	 */
	@JsonCreator
	public TextRegionLocation(@JsonProperty(LOCATION_PROPERTY) String location,
			@JsonProperty(UNIFORM_PATH_PROPERTY) String uniformPath,
			@JsonProperty(RAW_START_OFFSET_PROPERTY) int rawStartOffset,
			@JsonProperty(RAW_END_OFFSET_PROPERTY) int rawEndOffset,
			@JsonProperty(RAW_START_LINE_PROPERTY) int rawStartLine,
			@JsonProperty(RAW_END_LINE_PROPERTY) int rawEndLine) {
		super(location, uniformPath);

		CCSMAssert.isTrue(rawStartOffset <= rawEndOffset, "Start offset may not be after end offset.");
		CCSMAssert.isTrue(rawStartLine <= rawEndLine, "Start line may not be after end line.");

		this.rawStartOffset = rawStartOffset;
		this.rawEndOffset = rawEndOffset;
		this.rawStartLine = rawStartLine;
		this.rawEndLine = rawEndLine;
	}

	/**
	 * Returns the absolute start position of the region in the (raw) text (zero
	 * based, inclusive).
	 */
	public int getRawStartOffset() {
		return rawStartOffset;
	}

	/**
	 * Returns the absolute end position in the (raw) text (zero based, inclusive).
	 */
	public int getRawEndOffset() {
		return rawEndOffset;
	}

	/**
	 * Returns the line corresponding to {@link #getRawStartOffset()} (one-based,
	 * inclusive).
	 */
	public int getRawStartLine() {
		return rawStartLine;
	}

	/**
	 * Returns the line corresponding to {@link #getRawEndOffset()} (one-based,
	 * inclusive).
	 */
	public int getRawEndLine() {
		return rawEndLine;
	}

	/**
	 * {@inheritDoc}
	 * 

* This includes the start and end line which is typically sufficient for * debugging and showing to a user. */ @Override public String toLocationString() { return super.toLocationString() + ":" + rawStartLine + "-" + rawEndLine; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } TextRegionLocation that = (TextRegionLocation) o; return rawStartOffset == that.rawStartOffset && rawEndOffset == that.rawEndOffset && rawStartLine == that.rawStartLine && rawEndLine == that.rawEndLine; } @Override public int hashCode() { return Objects.hash(rawStartOffset, rawEndOffset, rawStartLine, rawEndLine); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy