Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/pjsofts/eurobudget/format/qif/QIFNonInvestmentItem.java


1   /*
2    * QIFNonInvestmentItem.java
3    *
4    */
5   
6   package com.pjsofts.eurobudget.format.qif;
7   
8   import com.pjsofts.eurobudget.DataModel;
9   import com.pjsofts.eurobudget.EBConstants;
10  import com.pjsofts.eurobudget.beans.*;
11  import java.io.IOException;
12  import java.text.ParseException;
13  import java.util.Date;
14  import java.util.ResourceBundle;
15  
16  
17  /** datas of group in QIF already a bit decoded without prefix letter 
18   <PRE>
19  Items for Non-Investment Accounts
20   
21  Each item in a bank, cash, credit card, other liability, or other asset account must begin with a letter that indicates the field in the Quicken register. The non-split items can be in any sequence:
22   
23  Field Indicator Explanation
24  D Date
25  T Amount
26  C Cleared status
27  N Num (check or reference number)
28  P Payee
29  M Memo
30  A Address (up to five lines; the sixth line is an optional message)
31  L Category (Category/Subcategory/Transfer/Class)
32  S Category in split (Category/Transfer/Class)
33  E Memo in split
34  $ Dollar amount of split
35  ^ End of the entry
36   
37  Note: Repeat the S, E, and $ lines as many times as needed for additional items in a split. If an item is omitted from the transaction in the QIF file, Quicken treats it as a blank item.
38  </PRE> 
39   */
40  public class QIFNonInvestmentItem {
41      private static final ResourceBundle i18n = EBConstants.i18n;
42      // corresponding Data decoded :
43      /** date */
44      public Date d = null;
45      /** cleared status */
46      public String c = null;
47      /** Memo */
48      public String m = null;
49      /** Memo in split */
50      public String e = null;
51      /** amount */
52      public Double t = null;
53      /** num (check or ref number as String ) */
54      public Long n = null;
55      /** Address (up to five lines; the sixth line is an optional message) */
56      public String a = null;
57      /** Payee */
58      public String p = null;
59      /** Category (Category/Subcategory/Transfer/Class)  */
60      public String l = null;//without []
61      /** is complex category */
62      boolean tl_with_brackets = false;
63      /**  Dollar amount of split */
64      public String dollardsign = null;
65      
66      public boolean isNull() {
67          return d == null && c == null && m == null && t == null
68          && n == null && p == null && l == null && a == null;
69      }
70  
71      /** export one transaction */
72      public static String toQIF(Transaction t) {
73          StringBuffer sb = new StringBuffer(50);
74          // DATE
75          sb.append("D");sb.append(QIF.DF.format(t.getDate()));
76          sb.append("\n");
77          // C TYPE
78          if ( t.isVerified() ) {
79              sb.append("CX\n");
80          } else if ( t.isChecked() ) {
81              sb.append("C*\n");
82          } else {
83              //nothing
84          }
85          // M
86          if ( t.getDetails() != null ) {
87              sb.append("M");
88              sb.append(t.getDetails());//t.getLibelle());
89              sb.append("\n");
90          }
91          // AMOUNT
92          sb.append("T");
93          sb.append(QIF.NF.format(t.getRealAmount()));
94          sb.append("\n");
95          // N, Check number
96          if ( t instanceof Check) {
97              Check c = (Check)t;
98              sb.append("N");
99              sb.append(c.getNumber().toString());
100             sb.append("\n");
101         }
102         // P
103         if ( t.getEntityName() != null && t.getEntityName().length() != 0 ) {
104             sb.append("P");
105             sb.append(t.getEntityName());
106             sb.append("\n");
107         }
108         // L Category
109         if ( t instanceof Virement) {
110             Virement v = (Virement)t;
111             sb.append("L");
112             sb.append("["+v.getTargetAccount().getName()+"]");
113             sb.append("\n");
114             // RelatedVirement need specific code ?? no
115         } else {
116             if ( t.getCategoryPair() != null && !t.getCategoryPair().isNull()
117             && t.getCategoryPair().getMain() != null
118             && t.getCategoryPair().getMain() != Category.CATEGORY_NULL ) {
119                 sb.append("L");
120                 sb.append(t.getCategoryPair().getMain().getName());
121                 if ( t.getCategoryPair().getSub() != null
122                 && t.getCategoryPair().getSub() != Category.CATEGORY_NULL ) {
123                     sb.append(":");
124                     sb.append(t.getCategoryPair().getSub().getName());
125                 }
126                 sb.append("\n");
127             }
128         }
129         // end of group
130         sb.append("^\n");
131         return sb.toString();
132     }    
133     
134     /**
135      * @param currentLine first line of the block of line
136      * @param break following lines
137      * @param checkRuleDT true means check rules:D,T Mandatory
138      *
139      * @return qif lines in their respective variables or null if all nulls
140      */
141     public static QIFNonInvestmentItem readItem(String currentLine, CacheReader br, boolean checkRuleDT) throws IOException, ParseException {
142         //Normal order = D,C,M,T,P,L
143         String line;
144         QIFNonInvestmentItem datas = new QIFNonInvestmentItem();
145         //
146         line = currentLine;
147         while ( line != null && !line.startsWith("^") ) {
148             if ( line.startsWith("D") ) {
149                 if ( datas.d != null ) {
150                     throw new ParseException(i18n.getString("QIF_error_D_duplicate"),br.getLineNumber());
151                 } else {
152                     try {
153                         line = line.trim().substring(1);
154                         line = line.replace('\'','/');//20yy, 19yy
155                         datas.d = QIF.DF.parse(line);
156                     } catch (ParseException pe){
157                         throw new ParseException(line,br.getLineNumber());
158                     }
159                 }
160             } else if ( line.startsWith("C") ) {
161                 line = line.trim().substring(1);
162                 if ( datas.c != null ) {
163                     throw new ParseException(i18n.getString("QIF_error_C_duplicate"),br.getLineNumber());
164                 } else {
165                     if ( !line.startsWith("*") && !line.startsWith("X") ) {
166                         // should not happend this should raise one exception during parsing only
167                         throw new ParseException(i18n.getString("QIF_error_C_decoding")+ " :"+line, br.getLineNumber());
168                     }
169                     datas.c = line;
170                 }
171             } else if ( line.startsWith("M") ) {
172                 line = line.trim().substring(1);
173                 if ( datas.m != null ) {
174                     //throw new java.text.ParseException(i18n.getString("QIF_error_M_duplicate"),br.getLineNumber());
175                     datas.m = datas.m + " " +line;
176                 } else {
177                     datas.m = line;
178                 }
179             } else if ( line.startsWith("N") ) {
180                 line = line.trim().substring(1);
181                 if ( datas.n != null ) {
182                     throw new ParseException(i18n.getString("QIF_error_N_duplicate"),br.getLineNumber());
183                 } else {
184                     try {
185                         datas.n = new Long(QIF.NF.parse(line).longValue());
186                     } catch (ParseException pe){
187                         // maybe a reference string that we discard ...
188                         if ( datas.m != null ) {
189                             datas.m = datas.m + " " +line;
190                         } else {
191                             datas.m = line;
192                         }
193                     }
194                 }
195             } else if ( line.startsWith("T") ) {
196                 line = line.trim().substring(1);
197                 if ( datas.t != null ) {
198                     throw new ParseException(i18n.getString("QIF_error_T_duplicate"),br.getLineNumber());
199                 } else {
200                     try {
201                         datas.t = new Double(QIF.NF.parse(line).doubleValue());
202                     } catch (ParseException pe){
203                         throw new ParseException(line,br.getLineNumber());
204                     }
205                 }
206             } else if ( line.startsWith("P") ) {
207                 line = line.trim().substring(1);
208                 if ( datas.p != null ) {
209                     throw new ParseException(i18n.getString("QIF_error_P_duplicate"),br.getLineNumber());
210                 } else {
211                     datas.p = line;
212                 }
213             } else if ( line.startsWith("A") ) {
214                 line = line.trim().substring(1);
215                 if ( datas.a != null ) {
216                     datas.a = datas.a + " "+ line;
217                 } else {
218                     datas.a = line;
219                 }
220             } else if ( line.startsWith("E") ) {
221                 line = line.trim().substring(1);
222                 if ( datas.e != null ) {
223                     datas.e = datas.e + " "+ line;
224                 } else {
225                     datas.e = line;
226                 }
227             } else if ( line.startsWith("$") ) {
228                 line= line.trim().substring(1);
229                 if ( datas.dollardsign != null ) {
230                     datas.dollardsign = datas.dollardsign + " "+ line;
231                 } else {
232                     datas.dollardsign = line;
233                 }
234             } else if ( line.startsWith("L") ) {
235                 line = line.trim().substring(1);
236                 if ( datas.l != null ) {
237                     throw new ParseException(i18n.getString("QIF_error_L_duplicate"),br.getLineNumber());
238                 } else {
239                     if ( line.startsWith("[") && line.endsWith("]") ) {
240                         datas.l = line.substring(1,line.length()-1);
241                         datas.tl_with_brackets = true;
242                     } else {
243                         datas.l = line;
244                         datas.tl_with_brackets = false;
245                     }
246                 }
247             } else if ( line.length() == 0 ) {
248                 // do nothing
249             } else throw new ParseException(i18n.getString("QIF_wrong_prefix")+line,br.getLineNumber());
250             line = br.readLine();
251         }
252         // Mandatory = D,T
253         if ( checkRuleDT && !datas.isNull() && (datas.d == null || datas.t == null ) ) {
254             throw new ParseException(i18n.getString("QIF_DT_mandatory"),br.getLineNumber());
255         }
256         if ( datas.isNull() )
257             return null;
258         return datas;
259     }
260     
261     /**
262      * Do any business logic rules to recreate a good transaction
263      * In charge of adding it to the right account(currentAccount most of the time, except for some virement).
264      * some params may be null
265      * precondition, c,d,t are not null
266      *
267      * @param dm DataModel used to created not existing entity, category ...
268      */
269     public static Transaction toEBTransaction(DataModel dm, Account currentAccount, QIFNonInvestmentItem datas) {
270         Transaction t = null;
271         boolean negativeAmount = datas.t.doubleValue() < 0.0d;
272         if ( datas.n != null ) {
273             // Check?
274             Check c = new Check();
275             t=c;
276             c.setNumber(datas.n);
277         } else if ( datas.l != null && datas.tl_with_brackets  ) {
278             // RelatedVirement?
279             // Virement?
280             Virement v = new Virement();
281             t=v;
282             Account targetAccount = dm.getAccountOrCreate(datas.l);
283             if ( negativeAmount ) {
284                 v.setSourceAccount(currentAccount);
285                 v.setTargetAccount(targetAccount);
286             } else {
287                 v.setSourceAccount(targetAccount);
288                 v.setTargetAccount(currentAccount);
289             }
290         } else if ( negativeAmount ) {
291             // Payment ?
292             t = new Payment();
293         } else {
294             // Versement ?
295             t = new Versement();
296         }
297         // C
298         if ( datas.c != null ) {
299             if ( datas.c.startsWith("*") ) {
300                 t.setChecked(true);
301             } else if ( datas.c.startsWith("X") ) {
302                 t.setChecked(true);
303                 t.setVerified(true);
304             } else {
305                 // should not happend this should raise one exception during parsing only
306             }
307         }
308         // D
309         t.setDate(datas.d);
310         // M
311         if ( datas.m != null )
312             t.setDetails(datas.m);
313         // T
314         t.setAmount(Math.abs(datas.t.doubleValue()));
315         // P/ Entity
316         if ( datas.p != null ) {
317             //should we create the entity if not Payment or Versement ??
318             Entity entity = dm.getEntityFromString(datas.p);
319             if ( t instanceof Payment ) {
320                 Payment payment = (Payment)t;
321                 payment.setToEntity(entity);
322             } else if (t instanceof Versement) {
323                 Versement v = (Versement)t;
324                 v.setFromEntity(entity);
325             } else {
326                 //this may happen, Money allows it
327                 //throw new java.text.ParseException("P/This entity is not in a Versement or Payment",br.getLineNumber());
328                 t.setDetails(t.getDetails()+" "+entity.getName());
329             }
330         }
331         // L / Category , not Bank Account !
332         if ( datas.l != null && !(t instanceof Virement) ) {
333             String cat1,cat2 = null;
334             int charind = datas.l.indexOf(":");
335             if ( charind < 0 ) {
336                 cat1 = datas.l; cat2 = null;
337             } else {
338                 cat1 = datas.l.substring(0,charind);
339                 cat2 = datas.l.substring(charind+1,datas.l.length());
340             }
341             int type =  (t instanceof Payment) ? CategoryPair.TYPE_COST : CategoryPair.TYPE_REVENUE;
342             Category category = dm.getCategoryFromString(cat1,type);
343             CategoryPair ct = new CategoryPair();
344             ct.setMain(category);
345             if ( cat2 != null) {
346                 Category subCategory = dm.getSubCategoryFromString(category, cat2,type);
347                 ct.setSub(subCategory);
348             }
349             t.setCategoryPair(ct);
350         }
351         
352         return t;
353     }
354    
355 }