1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.module.purap.util;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.struts.upload.FormFile;
20 import org.kuali.ole.module.purap.PurapConstants;
21 import org.kuali.ole.module.purap.PurapParameterConstants;
22 import org.kuali.ole.module.purap.businessobject.PurApItem;
23 import org.kuali.ole.module.purap.businessobject.PurchaseOrderItem;
24 import org.kuali.ole.module.purap.businessobject.RequisitionItem;
25 import org.kuali.ole.module.purap.exception.ItemParserException;
26 import org.kuali.ole.sys.OLEConstants;
27 import org.kuali.ole.sys.OLEKeyConstants;
28 import org.kuali.ole.sys.OLEPropertyConstants;
29 import org.kuali.ole.sys.context.SpringContext;
30 import org.kuali.ole.sys.service.impl.OleParameterConstants;
31 import org.kuali.rice.core.web.format.FormatException;
32 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
33 import org.kuali.rice.kns.service.DataDictionaryService;
34 import org.kuali.rice.krad.util.GlobalVariables;
35 import org.kuali.rice.krad.util.ObjectUtils;
36
37 import java.io.BufferedReader;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.io.InputStreamReader;
41 import java.lang.reflect.InvocationTargetException;
42 import java.util.ArrayList;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Map.Entry;
47
48 import static org.kuali.ole.module.purap.PurapKeyConstants.*;
49 import static org.kuali.ole.module.purap.PurapPropertyConstants.*;
50
51 public class ItemParserBase implements ItemParser {
52
53
54
55
56
57 protected static final String[] DEFAULT_FORMAT = {ITEM_QUANTITY, OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, ITEM_CATALOG_NUMBER, ITEM_COMMODITY_CODE, ITEM_DESCRIPTION, ITEM_UNIT_PRICE};
58 protected static final String[] COMMODITY_CODE_DISABLED_FORMAT = {ITEM_QUANTITY, OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE, ITEM_CATALOG_NUMBER, ITEM_DESCRIPTION, ITEM_UNIT_PRICE};
59
60 private Integer lineNo = 0;
61
62
63
64
65 public String[] getItemFormat() {
66
67
68
69 boolean enableCommodityCode = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_COMMODITY_CODE_IND);
70 if (enableCommodityCode) {
71 return DEFAULT_FORMAT;
72 }
73 return COMMODITY_CODE_DISABLED_FORMAT;
74 }
75
76
77
78
79 public String getExpectedItemFormatAsString(Class<? extends PurApItem> itemClass) {
80 checkItemClass(itemClass);
81 StringBuffer sb = new StringBuffer();
82 boolean first = true;
83 for (String attributeName : getItemFormat()) {
84 if (!first) {
85 sb.append(",");
86 } else {
87 first = false;
88 }
89 sb.append(getAttributeLabel(itemClass, attributeName));
90 }
91 return sb.toString();
92 }
93
94
95
96
97
98
99
100
101 @SuppressWarnings("rawtypes")
102 protected String getAttributeLabel(Class clazz, String attributeName) {
103 String label = SpringContext.getBean(DataDictionaryService.class).getAttributeLabel(clazz, attributeName);
104 if (StringUtils.isBlank(label)) {
105 label = attributeName;
106 }
107 return label;
108 }
109
110
111
112
113
114
115
116 protected void checkItemClass(Class<? extends PurApItem> itemClass) {
117 if (!PurApItem.class.isAssignableFrom(itemClass)) {
118 throw new IllegalArgumentException("unknown item class: " + itemClass);
119 }
120 }
121
122
123
124
125
126
127
128 protected void checkItemFile(FormFile itemFile) {
129 if (itemFile == null) {
130 throw new ItemParserException("invalid (null) item import file", OLEKeyConstants.ERROR_UPLOADFILE_NULL);
131 }
132 String fileName = itemFile.getFileName();
133 if (StringUtils.isNotBlank(fileName) && !StringUtils.lowerCase(fileName).endsWith(".csv") && !StringUtils.lowerCase(fileName).endsWith(".xls")) {
134 throw new ItemParserException("unsupported item import file format: " + fileName, ERROR_ITEMPARSER_INVALID_FILE_FORMAT, fileName);
135 }
136 }
137
138
139
140
141
142
143
144 protected Map<String, String> retrieveItemAttributes(String itemLine) {
145 String[] attributeNames = getItemFormat();
146 String[] attributeValues = StringUtils.splitPreserveAllTokens(itemLine, ',');
147 if (attributeNames.length != attributeValues.length) {
148 String[] errorParams = {"" + attributeNames.length, "" + attributeValues.length, "" + lineNo};
149 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERRORS, ERROR_ITEMPARSER_WRONG_PROPERTY_NUMBER, errorParams);
150 throw new ItemParserException("wrong number of item properties: " + attributeValues.length + " exist, " + attributeNames.length + " expected (line " + lineNo + ")", ERROR_ITEMPARSER_WRONG_PROPERTY_NUMBER, errorParams);
151 }
152
153 Map<String, String> itemMap = new HashMap<String, String>();
154 for (int i = 0; i < attributeNames.length; i++) {
155 itemMap.put(attributeNames[i], attributeValues[i]);
156 }
157 return itemMap;
158 }
159
160
161
162
163
164
165
166
167 protected PurApItem genItemWithRetrievedAttributes(Map<String, String> itemMap, Class<? extends PurApItem> itemClass) {
168 PurApItem item;
169 try {
170 item = itemClass.newInstance();
171 } catch (IllegalAccessException e) {
172 throw new IllegalArgumentException("unable to complete item line population.", e);
173 } catch (InstantiationException e) {
174 throw new IllegalArgumentException("unable to complete item line population.", e);
175 }
176
177 boolean failed = false;
178 for (Entry<String, String> entry : itemMap.entrySet()) {
179 String key = entry.getKey();
180 String value = entry.getValue();
181 try {
182
183
184
185
186
187
188 if (key.equals(OLEPropertyConstants.ITEM_UNIT_OF_MEASURE_CODE)) {
189 value = value.toUpperCase();
190 }
191 try {
192 ObjectUtils.setObjectProperty(item, key, value);
193 } catch (FormatException e) {
194 String[] errorParams = {value, key, "" + lineNo};
195 throw new ItemParserException("invalid numeric property value: " + key + " = " + value + " (line " + lineNo + ")", ERROR_ITEMPARSER_INVALID_NUMERIC_VALUE, errorParams);
196 }
197 } catch (ItemParserException e) {
198
199 GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERRORS, e.getErrorKey(), e.getErrorParameters());
200 failed = true;
201 } catch (IllegalAccessException e) {
202 throw new IllegalArgumentException("unable to complete item line population.", e);
203 } catch (NoSuchMethodException e) {
204 throw new IllegalArgumentException("unable to complete item line population.", e);
205 } catch (InvocationTargetException e) {
206 throw new IllegalArgumentException("unable to complete item line population.", e);
207 }
208 }
209
210 if (failed) {
211 throw new ItemParserException("empty or invalid item properties in line " + lineNo + ")", ERROR_ITEMPARSER_ITEM_PROPERTY, "" + lineNo);
212 }
213 return item;
214 }
215
216
217
218
219
220
221
222 protected void populateExtraAttributes(PurApItem item, String documentNumber) {
223 if (item.getItemQuantity() != null) {
224 String paramName = PurapParameterConstants.DEFAULT_QUANTITY_ITEM_TYPE;
225 String itemTypeCode = SpringContext.getBean(ParameterService.class).getParameterValueAsString(PurapConstants.PURAP_NAMESPACE, "Document", paramName);
226 item.setItemTypeCode(itemTypeCode);
227 } else {
228 String paramName = PurapParameterConstants.DEFAULT_NON_QUANTITY_ITEM_TYPE;
229 String itemTypeCode = SpringContext.getBean(ParameterService.class).getParameterValueAsString(PurapConstants.PURAP_NAMESPACE, "Document", paramName);
230 item.setItemTypeCode(itemTypeCode);
231 }
232 if (item instanceof RequisitionItem)
233 ((RequisitionItem) item).setItemRestrictedIndicator(false);
234 if (item instanceof PurchaseOrderItem)
235 ((PurchaseOrderItem) item).setDocumentNumber(documentNumber);
236 }
237
238
239
240
241 public PurApItem parseItem(String itemLine, Class<? extends PurApItem> itemClass, String documentNumber) {
242 Map<String, String> itemMap = retrieveItemAttributes(itemLine);
243 PurApItem item = genItemWithRetrievedAttributes(itemMap, itemClass);
244 populateExtraAttributes(item, documentNumber);
245 item.refresh();
246 return item;
247 }
248
249
250
251
252 public List<PurApItem> importItems(FormFile itemFile, Class<? extends PurApItem> itemClass, String documentNumber) {
253
254 try {
255 checkItemClass(itemClass);
256 checkItemFile(itemFile);
257 } catch (IllegalArgumentException e) {
258 throw new IllegalArgumentException("unable to import items.", e);
259 }
260
261
262 List<PurApItem> importedItems = new ArrayList<PurApItem>();
263 InputStream is;
264 BufferedReader br;
265 try {
266 is = itemFile.getInputStream();
267 br = new BufferedReader(new InputStreamReader(is));
268 } catch (IOException e) {
269 throw new IllegalArgumentException("unable to open import file in ItemParserBase.", e);
270 }
271
272
273 lineNo = 0;
274 boolean failed = false;
275 String itemLine = null;
276 try {
277 while ((itemLine = br.readLine()) != null) {
278 lineNo++;
279
280 if (StringUtils.isBlank(StringUtils.remove(StringUtils.deleteWhitespace(itemLine), OLEConstants.COMMA))) {
281 continue;
282 }
283
284 try {
285 PurApItem item = parseItem(itemLine, itemClass, documentNumber);
286 importedItems.add(item);
287 } catch (ItemParserException e) {
288
289
290 failed = true;
291 }
292 }
293
294 if (failed) {
295 throw new ItemParserException("errors in parsing item lines in file " + itemFile.getFileName(), ERROR_ITEMPARSER_ITEM_LINE, itemFile.getFileName());
296 }
297 } catch (IOException e) {
298 throw new IllegalArgumentException("unable to read line from BufferReader in ItemParserBase", e);
299 } finally {
300 try {
301 br.close();
302 } catch (IOException e) {
303 throw new IllegalArgumentException("unable to close BufferReader in ItemParserBase", e);
304 }
305 }
306
307 return importedItems;
308 }
309
310 }