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 }