View Javadoc
1   /*
2    * MoneyWise: Finance Application
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.moneywise.quicken.file;
18  
19  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity;
20  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityClass;
21  import io.github.tonywasher.joceanus.moneywise.quicken.definitions.MoneyWiseQLineType;
22  import io.github.tonywasher.joceanus.moneywise.quicken.definitions.MoneyWiseQSecurityLineType;
23  import io.github.tonywasher.joceanus.moneywise.quicken.file.MoneyWiseQIFLine.MoneyWiseQIFStringLine;
24  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
25  
26  import java.util.EnumMap;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Map.Entry;
31  import java.util.Objects;
32  
33  /**
34   * Class representing a QIF Security record.
35   */
36  public class MoneyWiseQIFSecurity
37          extends MoneyWiseQIFRecord<MoneyWiseQSecurityLineType>
38          implements Comparable<MoneyWiseQIFSecurity> {
39      /**
40       * Item type.
41       */
42      protected static final String QIF_ITEM = "Security";
43  
44      /**
45       * Category Map.
46       */
47      protected static final Map<MoneyWiseSecurityClass, String> QIF_ACTCATMAP = createClassMap();
48  
49      /**
50       * The Security.
51       */
52      private final String theName;
53  
54      /**
55       * The Symbol.
56       */
57      private final String theSymbol;
58  
59      /**
60       * The SecurityTypeClass.
61       */
62      private final MoneyWiseSecurityClass theClass;
63  
64      /**
65       * Constructor.
66       *
67       * @param pSecurity the Security
68       */
69      public MoneyWiseQIFSecurity(final MoneyWiseSecurity pSecurity) {
70          /* Call super-constructor */
71          super(MoneyWiseQSecurityLineType.class);
72  
73          /* Store data */
74          theName = pSecurity.getName();
75          theSymbol = pSecurity.getSymbol();
76          theClass = pSecurity.getCategoryClass();
77  
78          /* Build lines */
79          addLine(new MoneyWiseQIFSecurityNameLine(theName));
80          addLine(new MoneyWiseQIFSecuritySymbolLine(theSymbol));
81          addLine(new MoneyWiseQIFSecurityTypeLine(theClass));
82      }
83  
84      /**
85       * Constructor.
86       *
87       * @param pLines the data lines
88       */
89      protected MoneyWiseQIFSecurity(final List<String> pLines) {
90          /* Call super-constructor */
91          super(MoneyWiseQSecurityLineType.class);
92  
93          /* Determine details */
94          String myName = null;
95          String mySymbol = null;
96          MoneyWiseSecurityClass myClass = null;
97  
98          /* Loop through the lines */
99          final Iterator<String> myIterator = pLines.iterator();
100         while (myIterator.hasNext()) {
101             final String myLine = myIterator.next();
102 
103             /* Determine the category */
104             final MoneyWiseQSecurityLineType myType = MoneyWiseQSecurityLineType.parseLine(myLine);
105             if (myType != null) {
106                 /* Access data */
107                 final String myData = myLine.substring(myType.getSymbol().length());
108 
109                 /* Switch on line type */
110                 switch (myType) {
111                     case NAME:
112                         addLine(new MoneyWiseQIFSecurityNameLine(myData));
113                         myName = myData;
114                         break;
115                     case SYMBOL:
116                         addLine(new MoneyWiseQIFSecuritySymbolLine(myData));
117                         mySymbol = myData;
118                         break;
119                     case SECTYPE:
120                         final MoneyWiseQIFSecurityTypeLine myQLine = new MoneyWiseQIFSecurityTypeLine(myData);
121                         addLine(myQLine);
122                         myClass = myQLine.getSecurityClass();
123                         break;
124                     default:
125                         break;
126                 }
127             }
128         }
129 
130         /* Build details */
131         theName = myName;
132         theSymbol = mySymbol;
133         theClass = myClass;
134     }
135 
136     @Override
137     public String toString() {
138         return getName();
139     }
140 
141     /**
142      * Obtain the Name.
143      *
144      * @return the Name
145      */
146     public String getName() {
147         return theName;
148     }
149 
150     /**
151      * Obtain the symbol.
152      *
153      * @return the Name
154      */
155     public String getSymbol() {
156         return theSymbol;
157     }
158 
159     /**
160      * Create the CategoryClass to type map.
161      *
162      * @return the map
163      */
164     private static Map<MoneyWiseSecurityClass, String> createClassMap() {
165         /* Create the map */
166         final Map<MoneyWiseSecurityClass, String> myMap = new EnumMap<>(MoneyWiseSecurityClass.class);
167 
168         /* Add the entries */
169         myMap.put(MoneyWiseSecurityClass.SHARES, "Share");
170         myMap.put(MoneyWiseSecurityClass.GROWTHUNITTRUST, "Unit/Inv. Trust");
171         myMap.put(MoneyWiseSecurityClass.INCOMEUNITTRUST, "Unit/Inv. Trust");
172         myMap.put(MoneyWiseSecurityClass.LIFEBOND, "Bond");
173         myMap.put(MoneyWiseSecurityClass.ASSET, "Asset");
174         myMap.put(MoneyWiseSecurityClass.ENDOWMENT, "Trust");
175         myMap.put(MoneyWiseSecurityClass.VEHICLE, "Vehicle");
176         myMap.put(MoneyWiseSecurityClass.PROPERTY, "Real Estate");
177 
178         /* Return the map */
179         return myMap;
180     }
181 
182     @Override
183     public int compareTo(final MoneyWiseQIFSecurity pThat) {
184         return theName.compareTo(pThat.getName());
185     }
186 
187     /**
188      * The Security line.
189      *
190      * @param <X> the line type
191      */
192     public abstract static class MoneyWiseQIFSecurityLine<X extends MoneyWiseQLineType>
193             extends MoneyWiseQIFLine<X> {
194         /**
195          * The security.
196          */
197         private final MoneyWiseQIFSecurity theSecurity;
198 
199         /**
200          * Constructor.
201          *
202          * @param pSecurity the Security
203          */
204         protected MoneyWiseQIFSecurityLine(final MoneyWiseQIFSecurity pSecurity) {
205             /* Store data */
206             theSecurity = pSecurity;
207         }
208 
209         @Override
210         public String toString() {
211             return theSecurity.toString();
212         }
213 
214         /**
215          * Obtain account.
216          *
217          * @return the account
218          */
219         public MoneyWiseQIFSecurity getSecurity() {
220             return theSecurity;
221         }
222 
223         @Override
224         protected void formatData(final OceanusDataFormatter pFormatter,
225                                   final StringBuilder pBuilder) {
226             /* Append the security name */
227             pBuilder.append(theSecurity.getName());
228         }
229 
230         @Override
231         public boolean equals(final Object pThat) {
232             /* Handle trivial cases */
233             if (this == pThat) {
234                 return true;
235             }
236             if (pThat == null) {
237                 return false;
238             }
239 
240             /* Check class */
241             if (!getClass().equals(pThat.getClass())) {
242                 return false;
243             }
244 
245             /* Cast correctly */
246             final MoneyWiseQIFSecurityLine<?> myLine = (MoneyWiseQIFSecurityLine<?>) pThat;
247 
248             /* Check line type */
249             if (!getLineType().equals(myLine.getLineType())) {
250                 return false;
251             }
252 
253             /* Check value */
254             return theSecurity.equals(myLine.getSecurity());
255         }
256 
257         @Override
258         public int hashCode() {
259             return Objects.hash(getLineType(), theSecurity);
260         }
261     }
262 
263     /**
264      * The Security Name line.
265      */
266     public static class MoneyWiseQIFSecurityNameLine
267             extends MoneyWiseQIFStringLine<MoneyWiseQSecurityLineType> {
268         /**
269          * Constructor.
270          *
271          * @param pName the Name
272          */
273         protected MoneyWiseQIFSecurityNameLine(final String pName) {
274             /* Call super-constructor */
275             super(pName);
276         }
277 
278         @Override
279         public MoneyWiseQSecurityLineType getLineType() {
280             return MoneyWiseQSecurityLineType.NAME;
281         }
282 
283         /**
284          * Obtain name.
285          *
286          * @return the name
287          */
288         public String getName() {
289             return getValue();
290         }
291     }
292 
293     /**
294      * The Security Symbol line.
295      */
296     public static class MoneyWiseQIFSecuritySymbolLine
297             extends MoneyWiseQIFStringLine<MoneyWiseQSecurityLineType> {
298         /**
299          * Constructor.
300          *
301          * @param pSymbol the Symbol
302          */
303         protected MoneyWiseQIFSecuritySymbolLine(final String pSymbol) {
304             /* Call super-constructor */
305             super(pSymbol);
306         }
307 
308         @Override
309         public MoneyWiseQSecurityLineType getLineType() {
310             return MoneyWiseQSecurityLineType.SYMBOL;
311         }
312 
313         /**
314          * Obtain symbol.
315          *
316          * @return the symbol
317          */
318         public String getSymbol() {
319             return getValue();
320         }
321     }
322 
323     /**
324      * The Security Type line.
325      */
326     public static class MoneyWiseQIFSecurityTypeLine
327             extends MoneyWiseQIFStringLine<MoneyWiseQSecurityLineType> {
328         /**
329          * The Security Type Class.
330          */
331         private final MoneyWiseSecurityClass theClass;
332 
333         /**
334          * Constructor.
335          *
336          * @param pClass the Security Class
337          */
338         protected MoneyWiseQIFSecurityTypeLine(final MoneyWiseSecurityClass pClass) {
339             /* Call super-constructor */
340             super(QIF_ACTCATMAP.get(pClass));
341 
342             /* Record the class */
343             theClass = pClass;
344         }
345 
346         /**
347          * Constructor.
348          *
349          * @param pType the Security Type
350          */
351         protected MoneyWiseQIFSecurityTypeLine(final String pType) {
352             /* Call super-constructor */
353             super(pType);
354 
355             /* Loop through the map entries */
356             MoneyWiseSecurityClass myClass = null;
357             final Iterator<Entry<MoneyWiseSecurityClass, String>> myIterator = QIF_ACTCATMAP.entrySet().iterator();
358             while (myIterator.hasNext()) {
359                 final Entry<MoneyWiseSecurityClass, String> myEntry = myIterator.next();
360 
361                 /* If we have a match */
362                 if (pType.equals(myEntry.getValue())) {
363                     myClass = myEntry.getKey();
364                     break;
365                 }
366             }
367 
368             /* Store the class */
369             theClass = myClass;
370         }
371 
372         @Override
373         public MoneyWiseQSecurityLineType getLineType() {
374             return MoneyWiseQSecurityLineType.SECTYPE;
375         }
376 
377         @Override
378         public String toString() {
379             return theClass.toString();
380         }
381 
382         /**
383          * Obtain security class.
384          *
385          * @return the security class
386          */
387         public MoneyWiseSecurityClass getSecurityClass() {
388             return theClass;
389         }
390     }
391 }