001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 the ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.engine.commons.findings.location; 018 019import org.conqat.lib.commons.assertion.CCSMAssert; 020import org.conqat.lib.commons.js_export.ExportToJavaScript; 021 022import com.fasterxml.jackson.annotation.JsonCreator; 023import com.fasterxml.jackson.annotation.JsonProperty; 024 025/** 026 * This class denotes a region of text in an element. 027 * 028 * <b>Context:</b> Due to the way ConQAT deals with text, the class is a little 029 * bit more complex than expected. First, in ConQAT all text is normalized to 030 * use Unix style line endings (regardless of the line endings in the file). 031 * Second, ConQAT may apply filters, i.e. the internal (filtered) text 032 * representation may be different from the (raw) text in the file. 033 * Additionally, a location is best described by character offsets into the 034 * string, while a user typically expects line numbers. Conversion between all 035 * these representations is easy, as long as ConQAT internal representation is 036 * available. Without it, conversion is not possible. 037 * 038 * <b>Rationale:</b> When findings are reported to a user, the raw offsets 039 * and/or lines should be used, as these are more meaningful (visible in other 040 * editors as well). Also for persisting in a report, the raw positions are 041 * preferred, as the filtered ones depend on the ConQAT configuration, while raw 042 * offsets are independent of filter configuration. When working with findings 043 * within ConQAT, typically the filtered positions are needed, as most 044 * processors also work on the filtered representation. However, in such a case 045 * the corresponding element is typically available and thus conversion to the 046 * filtered representation is easy. 047 * 048 * <b>Implementation:</b> The finding (as well as the findings report) only 049 * stores raw positions. While the offsets would be sufficient, we also store 050 * line numbers to be able to provide meaningful user output. Filtered positions 051 * are not stored, but are made available via utility methods in the resource 052 * bundle. All fields are mandatory, i.e., it is not allowed to fill any 053 * position entry with invalid data (contrary to the old CodeRegionLocation, 054 * where -1 could be used to denote missing information). 055 */ 056@ExportToJavaScript 057public class TextRegionLocation extends ElementLocation { 058 059 /** 060 * Version used for serialization. 061 */ 062 private static final long serialVersionUID = 1; 063 064 /** 065 * An unknown offset used to indicate, that the line information is to be used 066 * to calculate character offset from. 067 */ 068 public static final int UNKNOWN_TEXT_REGION_OFFSET = -1; 069 070 /** 071 * The name of the JSON property name for {@link #rawStartOffset}. 072 */ 073 private static final String RAW_START_OFFSET_PROPERTY = "rawStartOffset"; 074 075 /** 076 * The name of the JSON property name for {@link #rawEndOffset}. 077 */ 078 private static final String RAW_END_OFFSET_PROPERTY = "rawEndOffset"; 079 080 /** 081 * The name of the JSON property name for {@link #rawStartLine}. 082 */ 083 private static final String RAW_START_LINE_PROPERTY = "rawStartLine"; 084 085 /** 086 * The name of the JSON property name for {@link #rawEndLine}. 087 */ 088 private static final String RAW_END_LINE_PROPERTY = "rawEndLine"; 089 090 /** 091 * The absolute start position of the region in the (raw) text (zero based, 092 * inclusive). 093 */ 094 @JsonProperty(RAW_START_OFFSET_PROPERTY) 095 private final int rawStartOffset; 096 097 /** 098 * The absolute end position in the (raw) text (zero based, inclusive). 099 */ 100 @JsonProperty(RAW_END_OFFSET_PROPERTY) 101 private final int rawEndOffset; 102 103 /** 104 * The line corresponding to {@link #rawStartOffset} (one-based, inclusive). 105 */ 106 @JsonProperty(RAW_START_LINE_PROPERTY) 107 private final int rawStartLine; 108 109 /** 110 * The line corresponding to {@link #rawEndOffset} (one-based, inclusive). 111 */ 112 @JsonProperty(RAW_END_LINE_PROPERTY) 113 private final int rawEndLine; 114 115 /** 116 * Constructor. 117 */ 118 @JsonCreator 119 public TextRegionLocation(@JsonProperty(LOCATION_PROPERTY) String location, 120 @JsonProperty(UNIFORM_PATH_PROPERTY) String uniformPath, 121 @JsonProperty(RAW_START_OFFSET_PROPERTY) int rawStartOffset, 122 @JsonProperty(RAW_END_OFFSET_PROPERTY) int rawEndOffset, 123 @JsonProperty(RAW_START_LINE_PROPERTY) int rawStartLine, 124 @JsonProperty(RAW_END_LINE_PROPERTY) int rawEndLine) { 125 super(location, uniformPath); 126 127 CCSMAssert.isTrue(rawStartOffset <= rawEndOffset, "Start offset may not be after end offset."); 128 CCSMAssert.isTrue(rawStartLine <= rawEndLine, "Start line may not be after end line."); 129 130 this.rawStartOffset = rawStartOffset; 131 this.rawEndOffset = rawEndOffset; 132 this.rawStartLine = rawStartLine; 133 this.rawEndLine = rawEndLine; 134 } 135 136 /** 137 * Returns the absolute start position of the region in the (raw) text (zero 138 * based, inclusive). 139 */ 140 public int getRawStartOffset() { 141 return rawStartOffset; 142 } 143 144 /** 145 * Returns the absolute end position in the (raw) text (zero based, inclusive). 146 */ 147 public int getRawEndOffset() { 148 return rawEndOffset; 149 } 150 151 /** 152 * Returns the line corresponding to {@link #getRawStartOffset()} (one-based, 153 * inclusive). 154 */ 155 public int getRawStartLine() { 156 return rawStartLine; 157 } 158 159 /** 160 * Returns the line corresponding to {@link #getRawEndOffset()} (one-based, 161 * inclusive). 162 */ 163 public int getRawEndLine() { 164 return rawEndLine; 165 } 166 167 /** 168 * {@inheritDoc} 169 * <p> 170 * This includes the start and end line which is typically sufficient for 171 * debugging and showing to a user. 172 */ 173 @Override 174 public String toLocationString() { 175 return super.toLocationString() + ":" + rawStartLine + "-" + rawEndLine; 176 } 177 178}