1 package com.atlassian.bonnie.search.extractor;
2
3 import com.atlassian.bonnie.Searchable;
4 import com.atlassian.bonnie.LuceneUtils;
5 import com.atlassian.bonnie.LuceneException;
6 import com.atlassian.bonnie.search.Extractor;
7 import com.atlassian.bonnie.search.DocumentBuilder;
8 import com.atlassian.bonnie.search.extractor.XmlClassConfigurations;
9 import com.atlassian.core.util.ObjectUtils;
10 import org.apache.commons.beanutils.PropertyUtils;
11 import org.apache.lucene.document.Document;
12 import org.apache.lucene.document.Field;
13
14 import java.lang.reflect.Array;
15 import java.lang.reflect.InvocationTargetException;
16 import java.util.Collection;
17 import java.util.Date;
18 import java.util.Iterator;
19
20 public class XmlConfiguredExtractor implements Extractor
21 {
22 public void addFields(Document document, StringBuffer defaultSearchableText, Searchable searchable)
23 {
24 XmlClassConfigurations.ClassConfiguration classConfig = XmlClassConfigurations.getClassConfiguration(ObjectUtils.getTrueClass(searchable));
25
26 if (classConfig != null)
27 {
28 Iterator iter = classConfig.getFieldConfigurations().iterator();
29 while (iter.hasNext())
30 {
31 XmlClassConfigurations.FieldConfiguration fieldConfiguration = (XmlClassConfigurations.FieldConfiguration) iter.next();
32 String attributeNames[] = fieldConfiguration.getAttributeName().split(",");
33 for (int i = 0; i < attributeNames.length; ++i)
34 {
35 Object o = getContentOfAttribute(searchable, attributeNames[i]);
36 if (o.getClass().isArray())
37 indexArrayField(document, fieldConfiguration, o);
38 else if (o instanceof Collection)
39 indexCollectionField(document, fieldConfiguration, (Collection) o);
40 else
41 if (o instanceof Date && fieldConfiguration.getType().equals(XmlClassConfigurations.FieldConfiguration.TYPE_KEYWORD))
42 indexDateField(document, fieldConfiguration, (Date) o);
43 else if (DocumentBuilder.CONTENT_FIELD_NAME.equals(fieldConfiguration.getFieldName()))
44 defaultSearchableText.append(String.valueOf(o));
45 else
46 indexStringField(document, fieldConfiguration, String.valueOf(o));
47 }
48 }
49 }
50 }
51
52 private void indexDateField(Document doc, XmlClassConfigurations.FieldConfiguration fieldConfiguration, Date date)
53 {
54 Field field = new Field(fieldConfiguration.getFieldName(), LuceneUtils.dateToString(date), Field.Store.YES, Field.Index.UN_TOKENIZED);
55 doc.add(field);
56 }
57
58 private void indexArrayField(Document doc, XmlClassConfigurations.FieldConfiguration fieldConfiguration, Object arr)
59 {
60 int length = Array.getLength(arr);
61 for (int i = 0; i < length; i++)
62 {
63 Object o = Array.get(arr, i);
64 indexStringField(doc, fieldConfiguration, String.valueOf(o));
65 }
66 }
67
68 private void indexCollectionField(Document doc, XmlClassConfigurations.FieldConfiguration fieldConfiguration, Collection collection)
69 {
70 for (Iterator it = collection.iterator(); it.hasNext();)
71 {
72 Object o = it.next();
73 indexStringField(doc, fieldConfiguration, String.valueOf(o));
74 }
75 }
76
77 private void indexStringField(Document doc, XmlClassConfigurations.FieldConfiguration fieldConfiguration, String strContent)
78 {
79 Field field;
80 if (fieldConfiguration.getType().equals(XmlClassConfigurations.FieldConfiguration.TYPE_TEXT))
81 {
82 field = new Field(fieldConfiguration.getFieldName(), strContent, Field.Store.YES, Field.Index.TOKENIZED);
83 }
84 else if (fieldConfiguration.getType().equals(XmlClassConfigurations.FieldConfiguration.TYPE_KEYWORD))
85 {
86 field = new Field(fieldConfiguration.getFieldName(), strContent, Field.Store.YES, Field.Index.UN_TOKENIZED);
87 }
88 else if (fieldConfiguration.getType().equals(XmlClassConfigurations.FieldConfiguration.TYPE_UNINDEXED))
89 {
90 field = new Field(fieldConfiguration.getFieldName(), strContent, Field.Store.YES, Field.Index.NO);
91 }
92 else if (fieldConfiguration.getType().equals(XmlClassConfigurations.FieldConfiguration.TYPE_UNSTORED))
93 {
94 field = new Field(fieldConfiguration.getFieldName(), strContent, Field.Store.NO, Field.Index.TOKENIZED);
95 }
96 else
97 {
98 throw new LuceneException("Unknown type for a field, fieldName=" + fieldConfiguration.getFieldName());
99 }
100
101 doc.add(field);
102 }
103
104 private Object getContentOfAttribute(Object obj, String attributeName)
105 {
106 try
107 {
108 String[] attributes = attributeName.split("\\.");
109 Object o = null;
110 for (int i = 0; i < attributes.length; ++i)
111 o = PropertyUtils.getProperty(obj, attributeName);
112 return (o == null) ? "" : o;
113 }
114 catch (IllegalAccessException iae)
115 {
116 throw new LuceneException("Couldn't get string content of attribute, as property accessor method for " + attributeName + " cannot be accessed");
117 }
118 catch (NoSuchMethodException e)
119 {
120 throw new LuceneException("Couldn't get string content of attribute, as no such property accessor method for " + attributeName + " exists");
121 }
122 catch (InvocationTargetException e)
123 {
124 throw new LuceneException("Calling property accessor method for attribute " + attributeName + " threw an exception", e);
125 }
126 }
127 }