1 package com.atlassian.bonnie;
2
3 import org.apache.lucene.document.DateField;
4 import org.apache.lucene.document.DateTools;
5 import org.apache.lucene.document.Document;
6 import org.apache.lucene.document.Field;
7 import org.apache.lucene.index.Term;
8 import org.apache.lucene.search.*;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11
12 import java.text.ParseException;
13 import java.util.*;
14 import java.util.concurrent.atomic.AtomicInteger;
15
16
17
18
19
20 public class LuceneUtils
21 {
22 private static final Logger log = LoggerFactory.getLogger(LuceneUtils.class);
23 private static final AtomicInteger invalidDateWarningCount = new AtomicInteger();
24 private static final int INVALID_DATE_MAX_WARNINGS = 20;
25
26
27
28
29
30
31 public static String dateToString(Date date)
32 {
33 return DateTools.dateToString(date, DateTools.Resolution.MILLISECOND);
34 }
35
36
37
38
39
40
41
42
43 public static Date stringToDate(String s)
44 {
45 if (s != null && s.trim().length() > 0)
46 {
47 try
48 {
49 return DateTools.stringToDate(s);
50 }
51 catch (ParseException e)
52 {
53 int currentErrorCount = invalidDateWarningCount.get();
54 if (currentErrorCount <= INVALID_DATE_MAX_WARNINGS) {
55 invalidDateWarningCount.incrementAndGet();
56 log.warn("Unable to parse a date found in the index because it uses an invalid encoding. Rebuilding the search index is recommended.");
57 if (currentErrorCount == INVALID_DATE_MAX_WARNINGS) {
58 log.warn("Suppressing more warnings about invalid dates until the application is restarted.");
59 }
60 }
61 return DateField.stringToDate(s);
62 }
63
64 }
65 return new Date();
66 }
67
68 public static Query buildSingleFieldSingleValueTermQuery(String field, String query)
69 {
70 return buildSingleFieldMultiValueTermQuery(field, Collections.singletonList(query), true);
71 }
72
73
74
75
76
77
78
79 public static Query buildSingleFieldMultiValueTermQuery(String field, Collection values, boolean andQuery)
80 {
81 BooleanQuery query = new BooleanQuery();
82
83 BooleanClause.Occur occur = andQuery ? BooleanClause.Occur.MUST : BooleanClause.Occur.SHOULD;
84
85 for (Iterator iterator = values.iterator(); iterator.hasNext();)
86 {
87 String value = (String) iterator.next();
88 query.add(new TermQuery(new Term(field, value)), occur);
89 }
90
91 return query;
92 }
93
94 public static Query buildSingleFieldMultiValuePrefixQuery(String field, Collection values, boolean andQuery)
95 {
96 BooleanQuery query = new BooleanQuery();
97
98 BooleanClause.Occur occur = andQuery ? BooleanClause.Occur.MUST : BooleanClause.Occur.SHOULD;
99
100 for (Iterator iterator = values.iterator(); iterator.hasNext();)
101 {
102 String value = (String) iterator.next();
103 query.add(new PrefixQuery(new Term(field, value)), occur);
104 }
105
106 return query;
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 public static Map buildMapFromDocument(Document doc)
124 {
125 Map result = new HashMap();
126 for (Iterator iter = doc.getFields().iterator(); iter.hasNext();)
127 {
128 Field f = (Field) iter.next();
129 String fieldname = f.name();
130 if (fieldname.indexOf('.') > -1)
131 {
132 String[] split = fieldname.split("\\.");
133 Map last = result;
134 for (int i = 0; i < split.length; ++i)
135 {
136 String key = split[i];
137 if (i == split.length - 1)
138 {
139 last.put(key, f.stringValue());
140 }
141 else
142 {
143 Object temp = last.get(key);
144 if (temp != null && !(temp instanceof Map))
145 {
146 break;
147 }
148
149 if (temp == null)
150 {
151 temp = new HashMap(5);
152 last.put(key, temp);
153 }
154 last = (Map) temp;
155 }
156 }
157 }
158 else
159 {
160 result.put(fieldname, f.stringValue());
161 }
162 }
163 return result;
164 }
165 }