View Javadoc

1   /*  Copyright 2004 Brian McCallister
2    *
3    *   Licensed under the Apache License, Version 2.0 (the "License");
4    *   you may not use this file except in compliance with the License.
5    *   You may obtain a copy of the License at
6    *
7    *       http://www.apache.org/licenses/LICENSE-2.0
8    *
9    *   Unless required by applicable law or agreed to in writing, software
10   *   distributed under the License is distributed on an "AS IS" BASIS,
11   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   *   See the License for the specific language governing permissions and
13   *   limitations under the License.
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                      //System.err.println(field_name + " : " + values.build(prop_value));
98                      document.add(field);
99                  }
100             }
101         }
102         // Now do immediate properties
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                 //System.err.println(field_name + " : " + values.build(prop_value));
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 }