1 /****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 ****************************************************************/
19
20 package org.apache.jsieve;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.jsieve.exception.CommandException;
24 import org.apache.jsieve.exception.SyntaxException;
25
26 /**
27 * Specifies the positional extent of an element within the script being
28 * executed. In other words, this gives the line and column at which the elment
29 * starts and at which it ends.
30 */
31 public final class ScriptCoordinate {
32
33 private final int startLineNumber;
34
35 private final int startColumnNumber;
36
37 private final int endLineNumber;
38
39 private final int endColumnNumber;
40
41 private Log log;
42
43 public ScriptCoordinate(final int startLineNumber,
44 final int startColumnNumber, final int endLineNumber,
45 final int endColumnNumber) {
46 super();
47 this.startLineNumber = startLineNumber;
48 this.startColumnNumber = startColumnNumber;
49 this.endLineNumber = endLineNumber;
50 this.endColumnNumber = endColumnNumber;
51 }
52
53 public Log getLog() {
54 return log;
55 }
56
57 public void setLog(Log logger) {
58 this.log = logger;
59 }
60
61 /**
62 * Gets the number of the column where the elements ends.
63 *
64 * @return column number
65 */
66 public int getEndColumnNumber() {
67 return endColumnNumber;
68 }
69
70 /**
71 * Gets the number of the line where the element ends.
72 *
73 * @return line number
74 */
75 public int getEndLineNumber() {
76 return endLineNumber;
77 }
78
79 /**
80 * Gets the number of the column where the element start.
81 *
82 * @return column number
83 */
84 public int getStartColumnNumber() {
85 return startColumnNumber;
86 }
87
88 /**
89 * Gets the number of the line where the element starts.
90 *
91 * @return line number
92 */
93 public int getStartLineNumber() {
94 return startLineNumber;
95 }
96
97 /**
98 * Creates a syntax exception based on the given message containing details
99 * of the script position. The message should end with a full stop.
100 *
101 * @param message
102 * <code>CharSequence</code> containing the base message, not
103 * null
104 * @return <code>SyntaxException</code> with details of the script
105 * position appended to the message, not null
106 */
107 public SyntaxException syntaxException(CharSequence message) {
108 if (log != null) {
109 if (log.isWarnEnabled()) {
110 log.warn(message);
111 }
112 logDiagnosticsInfo(log);
113 }
114 final String fullMessage = addStartLineAndColumn(message);
115 final SyntaxException result = new SyntaxException(fullMessage);
116 return result;
117 }
118
119 /**
120 * Creates a command exception based on the given message containing details
121 * of the script position. The message should end with a full stop.
122 *
123 * @param message
124 * <code>CharSequence</code> containing the base message, not
125 * null
126 * @return <code>CommandException</code> with details of the script
127 * position appended to the message, not null
128 */
129 public CommandException commandException(CharSequence message) {
130 if (log != null) {
131 if (log.isWarnEnabled()) {
132 log.warn(message);
133 }
134 logDiagnosticsInfo(log);
135 }
136 final String fullMessage = addStartLineAndColumn(message);
137 final CommandException result = new CommandException(fullMessage);
138 return result;
139 }
140
141 /**
142 * Appends a standard position phrase to the given message. This message
143 * should end with a full stop.
144 *
145 * @param message
146 * <code>CharSequence</code> message, not null
147 * @return <code>String</code> containing the original message with
148 * positional phrase appended, not null
149 */
150 public String addStartLineAndColumn(CharSequence message) {
151 final StringBuilder buffer;
152 if (message instanceof StringBuilder) {
153 buffer = (StringBuilder) message;
154 } else {
155 buffer = new StringBuilder(message.toString());
156 }
157 buffer.append(" Line ");
158 buffer.append(startLineNumber);
159 buffer.append(" column ");
160 buffer.append(startColumnNumber);
161 buffer.append(".");
162 return buffer.toString();
163 }
164
165 /**
166 * Logs diagnotic information about the script coordinate.
167 *
168 * @param logger
169 * <code>Log</code>, not null
170 */
171 public void logDiagnosticsInfo(Log logger) {
172 if (logger.isInfoEnabled()) {
173 logger.info("Expression starts line " + startLineNumber
174 + " column " + startColumnNumber);
175 logger.info("Expression ends line " + endLineNumber + " column "
176 + endColumnNumber);
177 }
178 }
179
180 /**
181 * Logs diagnotic information about the script coordinate.
182 *
183 * @param logger
184 * <code>Log</code>, not null
185 */
186 public void debugDiagnostics(Log logger) {
187 if (logger.isDebugEnabled()) {
188 logger.debug("Expression starts line " + startLineNumber
189 + " column " + startColumnNumber);
190 logger.debug("Expression ends line " + endLineNumber + " column "
191 + endColumnNumber);
192 }
193 }
194 }