1 package net.sf.sapjcosupport;
2
3 import org.apache.commons.beanutils.ConvertUtils;
4 import org.apache.log4j.Logger;
5
6 import java.lang.reflect.Field;
7 import java.text.DateFormat;
8 import java.text.ParseException;
9 import java.text.SimpleDateFormat;
10 import java.util.*;
11
12 /**
13 * This class implements the SAP <b>Search Help</b> functionality.
14 * <p/>
15 * As any subclass of <code>SapJcoInterface</code>, a value object is associated with this
16 * implementation: {@link SapSearchHelpVO}. This is a temporary value object, that can be mapped
17 * to the value object of your choice automagically.
18 * <br/>
19 * To do so, call the 'persistentObject' method with the class of the desired value object.
20 *
21 * @author Jo Vandermeeren
22 * @since Mar 21, 2006 - 11:08:01 AM
23 */
24 public abstract class SapSearchHelp extends SapJcoInterface {
25 protected final Logger log = Logger.getLogger(getClass());
26 protected static final DateFormat SAP_DATE_FORMATTER = new SimpleDateFormat("yyyyMMdd");
27
28 /**
29 * Performs the actual search. Call this method after you have set all necessary properties.
30 * <br/>
31 * If the persistent object class was not set, instances of <code>SearchHelpVO</code> are returned.
32 * <p/>
33 * Each field in the 'javaFieldSelection' list should correspond with a field at the same position in the 'sapFieldSelection' list.
34 *
35 * @param searchHelpName name of the SAP search help
36 * @param selectionMethod name of the selection method for the search help
37 * @param maximumResults maximum results to return
38 * @param criteria list of {@link SearchCriterion} objects
39 * @param persistentObject value object class
40 * @param javaFieldSelection list of the names of the Java value object fields
41 * @param sapFieldSelection list of the names of the SAP function fields
42 * @return List containing the search results as instances of the same type as specified by 'persistentObject'.
43 * @throws IllegalArgumentException if the lists are null, empty or of different size; if the 'searchHelpName' or selectionMethod parameters are null
44 */
45 public List search(String searchHelpName, String selectionMethod, int maximumResults, List criteria, Class persistentObject, List javaFieldSelection, List sapFieldSelection) {
46 int sapSearchHelpVOFieldCount = SapSearchHelpVO.getFieldCount();
47 if (javaFieldSelection == null || sapFieldSelection == null || sapFieldSelection.size() == 0 || sapFieldSelection.size() > sapSearchHelpVOFieldCount)
48 {
49 throw new IllegalArgumentException("Field lists should not be null, should contain at least 1, and max. " + sapSearchHelpVOFieldCount + " elements");
50 }
51 if (javaFieldSelection.size() != sapFieldSelection.size()) {
52 throw new IllegalArgumentException("For each item in the SAP field list, the java field list should have a value at the same position");
53 }
54 Map searchInput = new HashMap(5);
55 if (searchHelpName == null) {
56 throw new IllegalArgumentException("You have to specify the searchHelpName");
57 }
58 if (selectionMethod == null) {
59 throw new IllegalArgumentException("You have to specify the selectionMethod");
60 }
61 searchInput.put("SEARCHHELPNAME", searchHelpName);
62 searchInput.put("SEARCHHELPMETHOD", selectionMethod);
63 searchInput.put("MAX_ROWS", String.valueOf(maximumResults));
64
65
66 List selectionCriteria = new ArrayList(criteria.size());
67 for (Iterator i = criteria.iterator(); i.hasNext();) {
68 SearchCriterion criterion = (SearchCriterion) i.next();
69 if (criterion != null) {
70 selectionCriteria.add(criterion.toMap());
71 }
72 }
73 searchInput.put("SELECTIONCRITERIA", selectionCriteria);
74
75
76 searchInput.put("FIELDLIST", sapFieldSelection);
77
78
79 List results = (List) retrieve(SapSearchHelpVO.class, searchInput, null);
80
81
82 if (persistentObject == null) {
83 return results;
84 }
85 List persistentObjects = new ArrayList(results.size());
86 for (Iterator i = results.iterator(); i.hasNext();) {
87 SapSearchHelpVO vo = (SapSearchHelpVO) i.next();
88 Object object = convertSearchHelpVO(vo, persistentObject, javaFieldSelection);
89 if (object != null) {
90 persistentObjects.add(object);
91 }
92 i.remove();
93 }
94 return persistentObjects;
95 }
96
97 /**
98 * Helper method to convert SearchHelpVO instances to instances of the same type as specified by 'persistentObject'.
99 *
100 * @param valueObject search result (internal format)
101 * @param persistentObject class of the desired value object; must have a defined zero-args constructor
102 * @param javaFieldSelection fields
103 * @return instance of the same type as specified by 'persistentObject'.
104 */
105 private Object convertSearchHelpVO(SapSearchHelpVO valueObject, Class persistentObject, List javaFieldSelection) {
106 Class valueObjectClass = valueObject.getClass();
107 try {
108 Object instance = persistentObject.newInstance();
109 int i = 0;
110 for (Iterator valueIterator = valueObject.iterator(); i < javaFieldSelection.size() && valueIterator.hasNext(); i++)
111 {
112 Object value = valueIterator.next();
113 if (value == null) {
114 continue;
115 }
116 String fieldName = (String) javaFieldSelection.get(i);
117 Field field = persistentObject.getDeclaredField(fieldName);
118 field.setAccessible(true);
119 Object convertedValue = null;
120 if (Date.class.equals(field.getType())) {
121 try {
122 convertedValue = SAP_DATE_FORMATTER.parse((String) value);
123 } catch (ParseException e) {
124 log.warn("Unable to parse " + value + " as a date for field " + field.getName());
125 }
126 } else {
127 convertedValue = ConvertUtils.convert((String) value, field.getType());
128 }
129 field.set(instance, convertedValue);
130 }
131 return instance;
132 } catch (InstantiationException e) {
133 log.warn("Can not instantiate class " + persistentObject.getClass(), e);
134 } catch (IllegalAccessException e) {
135 log.warn("Can not set a field in class " + persistentObject.getClass() + " or get field in class " + valueObjectClass, e);
136 } catch (NoSuchFieldException e) {
137 log.warn("Can not find a field in class " + persistentObject + " or in class " + valueObjectClass, e);
138 }
139 return null;
140 }
141 }