1 package org.apache.lucene.search.highlight;
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 * Formats text with different color intensity depending on the score of the
24 public class GradientFormatter implements Formatter
26 private float maxScore;
28 int fgRMin, fgGMin, fgBMin;
30 int fgRMax, fgGMax, fgBMax;
32 protected boolean highlightForeground;
34 int bgRMin, bgGMin, bgBMin;
36 int bgRMax, bgGMax, bgBMax;
38 protected boolean highlightBackground;
41 * Sets the color range for the IDF scores
44 * The score (and above) displayed as maxColor (See QueryScorer.getMaxWeight
45 * which can be used to calibrate scoring scale)
46 * @param minForegroundColor
47 * The hex color used for representing IDF scores of zero eg
48 * #FFFFFF (white) or null if no foreground color required
49 * @param maxForegroundColor
50 * The largest hex color used for representing IDF scores eg
51 * #000000 (black) or null if no foreground color required
52 * @param minBackgroundColor
53 * The hex color used for representing IDF scores of zero eg
54 * #FFFFFF (white) or null if no background color required
55 * @param maxBackgroundColor
56 * The largest hex color used for representing IDF scores eg
57 * #000000 (black) or null if no background color required
59 public GradientFormatter(float maxScore, String minForegroundColor,
60 String maxForegroundColor, String minBackgroundColor,
61 String maxBackgroundColor)
63 highlightForeground = (minForegroundColor != null)
64 && (maxForegroundColor != null);
65 if (highlightForeground)
67 if (minForegroundColor.length() != 7)
69 throw new IllegalArgumentException(
70 "minForegroundColor is not 7 bytes long eg a hex "
71 + "RGB value such as #FFFFFF");
73 if (maxForegroundColor.length() != 7)
75 throw new IllegalArgumentException(
76 "minForegroundColor is not 7 bytes long eg a hex "
77 + "RGB value such as #FFFFFF");
79 fgRMin = hexToInt(minForegroundColor.substring(1, 3));
80 fgGMin = hexToInt(minForegroundColor.substring(3, 5));
81 fgBMin = hexToInt(minForegroundColor.substring(5, 7));
83 fgRMax = hexToInt(maxForegroundColor.substring(1, 3));
84 fgGMax = hexToInt(maxForegroundColor.substring(3, 5));
85 fgBMax = hexToInt(maxForegroundColor.substring(5, 7));
88 highlightBackground = (minBackgroundColor != null)
89 && (maxBackgroundColor != null);
90 if (highlightBackground)
92 if (minBackgroundColor.length() != 7)
94 throw new IllegalArgumentException(
95 "minBackgroundColor is not 7 bytes long eg a hex "
96 + "RGB value such as #FFFFFF");
98 if (maxBackgroundColor.length() != 7)
100 throw new IllegalArgumentException(
101 "minBackgroundColor is not 7 bytes long eg a hex "
102 + "RGB value such as #FFFFFF");
104 bgRMin = hexToInt(minBackgroundColor.substring(1, 3));
105 bgGMin = hexToInt(minBackgroundColor.substring(3, 5));
106 bgBMin = hexToInt(minBackgroundColor.substring(5, 7));
108 bgRMax = hexToInt(maxBackgroundColor.substring(1, 3));
109 bgGMax = hexToInt(maxBackgroundColor.substring(3, 5));
110 bgBMax = hexToInt(maxBackgroundColor.substring(5, 7));
112 // this.corpusReader = corpusReader;
113 this.maxScore = maxScore;
114 // totalNumDocs = corpusReader.numDocs();
117 public String highlightTerm(String originalText, TokenGroup tokenGroup)
119 if (tokenGroup.getTotalScore() == 0)
121 float score = tokenGroup.getTotalScore();
126 StringBuilder sb = new StringBuilder();
128 if (highlightForeground)
130 sb.append("color=\"");
131 sb.append(getForegroundColorString(score));
134 if (highlightBackground)
136 sb.append("bgcolor=\"");
137 sb.append(getBackgroundColorString(score));
141 sb.append(originalText);
142 sb.append("</font>");
143 return sb.toString();
146 protected String getForegroundColorString(float score)
148 int rVal = getColorVal(fgRMin, fgRMax, score);
149 int gVal = getColorVal(fgGMin, fgGMax, score);
150 int bVal = getColorVal(fgBMin, fgBMax, score);
151 StringBuilder sb = new StringBuilder();
153 sb.append(intToHex(rVal));
154 sb.append(intToHex(gVal));
155 sb.append(intToHex(bVal));
156 return sb.toString();
159 protected String getBackgroundColorString(float score)
161 int rVal = getColorVal(bgRMin, bgRMax, score);
162 int gVal = getColorVal(bgGMin, bgGMax, score);
163 int bVal = getColorVal(bgBMin, bgBMax, score);
164 StringBuilder sb = new StringBuilder();
166 sb.append(intToHex(rVal));
167 sb.append(intToHex(gVal));
168 sb.append(intToHex(bVal));
169 return sb.toString();
172 private int getColorVal(int colorMin, int colorMax, float score)
174 if (colorMin == colorMax)
178 float scale = Math.abs(colorMin - colorMax);
179 float relScorePercent = Math.min(maxScore, score) / maxScore;
180 float colScore = scale * relScorePercent;
181 return Math.min(colorMin, colorMax) + (int) colScore;
184 private static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7',
185 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
187 private static String intToHex(int i)
189 return "" + hexDigits[(i & 0xF0) >> 4] + hexDigits[i & 0x0F];
193 * Converts a hex string into an int. Integer.parseInt(hex, 16) assumes the
194 * input is nonnegative unless there is a preceding minus sign. This method
195 * reads the input as twos complement instead, so if the input is 8 bytes
196 * long, it will correctly restore a negative int produced by
197 * Integer.toHexString() but not necessarily one produced by
198 * Integer.toString(x,16) since that method will produce a string like '-FF'
199 * for negative integer values.
202 * A string in capital or lower case hex, of no more then 16
204 * @throws NumberFormatException
205 * if the string is more than 16 characters long, or if any
206 * character is not in the set [0-9a-fA-f]
208 public static final int hexToInt(String hex)
210 int len = hex.length();
212 throw new NumberFormatException();
215 for (int i = 0; i < len; i++)
218 int c = Character.digit(hex.charAt(i), 16);
220 throw new NumberFormatException();