1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.skife.lucene.graph;
16
17 import org.apache.commons.beanutils.PropertyUtils;
18 import org.apache.commons.logging.LogFactory;
19 import org.apache.lucene.document.Document;
20 import org.apache.lucene.document.Field;
21
22 import java.beans.PropertyDescriptor;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.Stack;
26
27 /***
28 * Used to build </code>root.property.property</code> style fields
29 */
30 class PropertyChain
31 {
32 private final Stack stack = new Stack();
33 private final HashMap map = new HashMap();
34 private final NameMapper names;
35 private final ValueMapper values;
36
37 PropertyChain(final NameMapper names,
38 final ValueMapper values)
39 {
40 this.names = names;
41 this.values = values;
42 }
43
44 /***
45 * Called the first time an entity is found
46 */
47 void visited(final Object current, final Document doc)
48 {
49 map.put(current, doc);
50 buildUpStackFields(current);
51 stack.push(current);
52 }
53
54 /***
55 * Called when an instance is found additional times in a cyclic graph
56 */
57 void reVisited(final Object current)
58 {
59 buildUpStackFields(current);
60 buildDownStackFields(current);
61 }
62
63 private void buildUpStackFields(final Object current)
64 {
65 final Stack local_stack = new Stack();
66 for (Iterator i = stack.iterator(); i.hasNext();) local_stack.push(i.next());
67 String trailer = names.build(current);
68 while (!local_stack.isEmpty())
69 {
70 final Object value = local_stack.pop();
71 trailer = names.build(value) + "." + trailer;
72 final Document document = (Document) map.get(value);
73
74 final Field current_field = Field.Text(trailer, values.build(current));
75 document.add(current_field);
76
77 trailer = trailer + ".";
78
79 final PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(current);
80 for (int i = 0; i != properties.length; i++)
81 {
82 final PropertyDescriptor property = properties[i];
83 if (IndexBuilder.isIndexedProperty(property))
84 {
85 final Object prop_value;
86 try
87 {
88 prop_value = PropertyUtils.getProperty(current, property.getName());
89 }
90 catch (Exception e)
91 {
92 e.printStackTrace();
93 continue;
94 }
95 final String field_name = trailer + property.getName();
96 final Field field = Field.Text(field_name, values.build(prop_value));
97
98 document.add(field);
99 }
100 }
101 }
102
103 final String current_name_and_dot = names.build(current) + ".";
104 final Document document = (Document) map.get(current);
105 final PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(current);
106 for (int i = 0; i != properties.length; i++)
107 {
108 final PropertyDescriptor property = properties[i];
109 if (IndexBuilder.isIndexedProperty(property))
110 {
111 final Object prop_value;
112 try
113 {
114 prop_value = PropertyUtils.getProperty(current, property.getName());
115 }
116 catch (Exception e)
117 {
118 LogFactory.getLog(PropertyChain.class).error("Unable to access property: " + e.getMessage(), e);
119 continue;
120 }
121 final String field_name = current_name_and_dot + property.getName();
122 final Field field = Field.Text(field_name, values.build(prop_value));
123
124
125 document.add(field);
126 }
127 }
128 }
129
130
131 private void buildDownStackFields(final Object current)
132 {
133 LogFactory.getLog(PropertyChain.class).warn("Presently, cyclic graphs are not indexed correctly");
134
135 }
136
137 /***
138 * Look at the last instance passed in
139 */
140 Object peek()
141 {
142 if (stack.isEmpty()) return null;
143 return stack.peek();
144 }
145
146 Object pop()
147 {
148 return stack.pop();
149 }
150
151 void clear()
152 {
153 stack.clear();
154 map.clear();
155 }
156 }