View Javadoc
1   /*
2    *  jDTAUS Banking RI CurrencyDirectory
3    *  Copyright (C) 2005 Christian Schulte
4    *  <cs@schulte.it>
5    *
6    *  This library is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public
8    *  License as published by the Free Software Foundation; either
9    *  version 2.1 of the License, or any later version.
10   *
11   *  This library is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this library; if not, write to the Free Software
18   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19   *
20   */
21  package org.jdtaus.banking.ri.currencydir;
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.net.URI;
27  import java.net.URISyntaxException;
28  import java.net.URL;
29  import java.text.DateFormat;
30  import java.text.ParseException;
31  import java.text.SimpleDateFormat;
32  import java.util.ArrayList;
33  import java.util.Arrays;
34  import java.util.Calendar;
35  import java.util.Collection;
36  import java.util.Currency;
37  import java.util.Date;
38  import java.util.HashMap;
39  import java.util.HashSet;
40  import java.util.Iterator;
41  import java.util.LinkedList;
42  import java.util.Locale;
43  import java.util.Map;
44  import javax.xml.parsers.DocumentBuilder;
45  import javax.xml.parsers.DocumentBuilderFactory;
46  import javax.xml.parsers.ParserConfigurationException;
47  import org.jdtaus.banking.messages.ReadsCurrenciesMessage;
48  import org.jdtaus.banking.messages.SearchesCurrenciesMessage;
49  import org.jdtaus.banking.spi.CurrencyMapper;
50  import org.jdtaus.banking.spi.UnsupportedCurrencyException;
51  import org.jdtaus.core.container.ContainerFactory;
52  import org.jdtaus.core.container.PropertyException;
53  import org.jdtaus.core.logging.spi.Logger;
54  import org.jdtaus.core.monitor.spi.Task;
55  import org.jdtaus.core.monitor.spi.TaskMonitor;
56  import org.jdtaus.core.sax.util.EntityResolverChain;
57  import org.w3c.dom.Document;
58  import org.w3c.dom.Element;
59  import org.w3c.dom.NodeList;
60  import org.xml.sax.ErrorHandler;
61  import org.xml.sax.SAXException;
62  import org.xml.sax.SAXParseException;
63  
64  /**
65   * Currency directory implementation backed by XML resources.
66   * <p>This implementation uses XML resources provided by any available {@link JaxpCurrenciesProvider} implementation.
67   * Resources with a {@code file} URI scheme are monitored for changes by querying the last modification time. Monitoring
68   * is controlled by property {@code reloadIntervalMillis}.</p>
69   *
70   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
71   * @version $JDTAUS: JaxpCurrencyDirectory.java 8865 2014-01-10 17:13:42Z schulte $
72   */
73  public class JaxpCurrencyDirectory implements CurrencyMapper
74  {
75  
76      /** JAXP configuration key to the Schema implementation attribute. */
77      private static final String SCHEMA_LANGUAGE_KEY = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
78  
79      /** JAXP Schema implementation to use. */
80      private static final String SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema";
81  
82      /** jDTAUS {@code currencies} namespace URI. */
83      private static final String CURRENCIES_NS = "http://jdtaus.org/banking/xml/currencies";
84  
85      /** jDTAUS {@code banking} namespace URI. */
86      private static final String BANKING_NS = "http://jdtaus.org/banking/model";
87  
88      /** {@code http://www.w3.org/2001/XMLSchema-instance} namespace URI. */
89      private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
90  
91      /** Version supported by this implementation. */
92      private static final String[] SUPPORTED_VERSIONS =
93      {
94          "1.0"
95      };
96  
97      /** Flag indicating that initialization has been performed. */
98      private boolean initialized;
99  
100     /** Maps ISO codes to currency instances. */
101     private final Map isoMap = new HashMap();
102 
103     /** Maps DTAUS codes to currency instances. */
104     private final Map dtausMap = new HashMap();
105 
106     /** Maps {@code File} instances to theire last modification timestamp. */
107     private final Map monitorMap = new HashMap();
108 
109     /** Holds the timestamp resources got checked for modifications. */
110     private long lastCheck = System.currentTimeMillis();
111 
112     /** Number of milliseconds to pass before resources are checked for modifications. */
113     private Long reloadIntervalMillis;
114 
115     /** Number of currencies for which progress monitoring gets enabled. */
116     private Long monitoringThreshold;
117 
118     /**
119      * Creates a new {@code JaxpCurrencyDirectory} instance taking the number of milliseconds to pass before resources
120      * are checked for modifications and the number of currencies for which progress monitoring gets enabled.
121      *
122      * @param reloadIntervalMillis Number of milliseconds to pass before resources are checked for modifications.
123      * @param monitoringThreshold Number of currencies for which progress monitoring gets enabled.
124      */
125     public JaxpCurrencyDirectory( final long reloadIntervalMillis, final long monitoringThreshold )
126     {
127         this();
128         if ( reloadIntervalMillis > 0 )
129         {
130             this.reloadIntervalMillis = new Long( reloadIntervalMillis );
131         }
132         if ( monitoringThreshold > 0 )
133         {
134             this.monitoringThreshold = new Long( monitoringThreshold );
135         }
136     }
137 
138     /**
139      * Gets the number of milliseconds to pass before resources are checked for modifications.
140      *
141      * @return The number of milliseconds to pass before resources are checked for modifications.
142      */
143     public long getReloadIntervalMillis()
144     {
145         if ( this.reloadIntervalMillis == null )
146         {
147             this.reloadIntervalMillis = this.getDefaultReloadIntervalMillis();
148         }
149 
150         return this.reloadIntervalMillis.longValue();
151     }
152 
153     /**
154      * Gets the number of currencies for which progress monitoring gets enabled.
155      *
156      * @return The number of currencies for which progress monitoring gets enabled.
157      */
158     public long getMonitoringThreshold()
159     {
160         if ( this.monitoringThreshold == null )
161         {
162             this.monitoringThreshold = this.getDefaultMonitoringThreshold();
163         }
164 
165         return this.monitoringThreshold.longValue();
166     }
167 
168     public Currency[] getDtausCurrencies( final Date date )
169     {
170         if ( date == null )
171         {
172             throw new NullPointerException( "date" );
173         }
174 
175         this.assertValidProperties();
176         this.assertInitialized();
177 
178         final Collection col = new LinkedList();
179 
180         if ( !this.isoMap.isEmpty() )
181         {
182             final Task task = new Task();
183             task.setCancelable( true );
184             task.setDescription( new SearchesCurrenciesMessage() );
185             task.setIndeterminate( false );
186             task.setMaximum( this.isoMap.size() );
187             task.setMinimum( 0 );
188 
189             int progress = 0;
190             task.setProgress( progress );
191 
192             try
193             {
194                 if ( task.getMaximum() > this.getMonitoringThreshold() )
195                 {
196                     this.getTaskMonitor().monitor( task );
197                 }
198 
199                 for ( final Iterator it = this.isoMap.keySet().iterator(); it.hasNext() && !task.isCancelled(); )
200                 {
201                     task.setProgress( progress++ );
202                     final String isoCode = (String) it.next();
203                     final JaxpCurrency currency = (JaxpCurrency) this.isoMap.get( isoCode );
204 
205                     if ( currency.isValidAt( date ) )
206                     {
207                         col.add( Currency.getInstance( isoCode ) );
208                     }
209                 }
210 
211                 if ( task.isCancelled() )
212                 {
213                     col.clear();
214                 }
215             }
216             finally
217             {
218                 if ( task.getMaximum() > this.getMonitoringThreshold() )
219                 {
220                     this.getTaskMonitor().finish( task );
221                 }
222             }
223         }
224 
225         return (Currency[]) col.toArray( new Currency[ col.size() ] );
226     }
227 
228     public Currency getDtausCurrency( final char code, final Date date )
229     {
230         if ( date == null )
231         {
232             throw new NullPointerException( "date" );
233         }
234 
235         this.assertValidProperties();
236         this.assertInitialized();
237 
238         final JaxpCurrency currency = (JaxpCurrency) this.dtausMap.get( new Character( code ) );
239         Currency ret = null;
240 
241         if ( currency != null && currency.isValidAt( date ) )
242         {
243             ret = Currency.getInstance( currency.getIsoCode() );
244         }
245 
246         return ret;
247     }
248 
249     public char getDtausCode( final Currency currency, final Date date )
250     {
251         if ( currency == null )
252         {
253             throw new NullPointerException( "currency" );
254         }
255         if ( date == null )
256         {
257             throw new NullPointerException( "date" );
258         }
259 
260         this.assertValidProperties();
261         this.assertInitialized();
262 
263         final JaxpCurrency xml = (JaxpCurrency) this.isoMap.get( currency.getCurrencyCode() );
264 
265         if ( xml != null && xml.getDtausCode() != null && xml.isValidAt( date ) )
266         {
267             return xml.getDtausCode().charValue();
268         }
269 
270         throw new UnsupportedCurrencyException( currency.getCurrencyCode(), date );
271     }
272 
273     /**
274      * Initializes the instance to hold the parsed XML currency instances.
275      *
276      * @see #assertValidProperties()
277      * @see #parseResources()
278      * @see #transformDocument(Document)
279      */
280     private synchronized void assertInitialized()
281     {
282         try
283         {
284             if ( System.currentTimeMillis() - this.lastCheck > this.getReloadIntervalMillis()
285                  && !this.monitorMap.isEmpty() )
286             {
287                 this.lastCheck = System.currentTimeMillis();
288                 for ( final Iterator it = this.monitorMap.entrySet().iterator(); it.hasNext(); )
289                 {
290                     final Map.Entry entry = (Map.Entry) it.next();
291                     final File file = (File) entry.getKey();
292                     final Long lastModified = (Long) entry.getValue();
293                     assert lastModified != null : "Expected modification time.";
294 
295                     if ( file.lastModified() != lastModified.longValue() )
296                     {
297                         this.getLogger().info( this.getChangeInfoMessage( this.getLocale(), file.getAbsolutePath() ) );
298                         this.initialized = false;
299                         break;
300                     }
301                 }
302             }
303 
304             if ( !this.initialized )
305             {
306                 this.monitorMap.clear();
307                 this.isoMap.clear();
308                 this.dtausMap.clear();
309 
310                 final Document[] docs = this.parseResources();
311                 final Collection col = new LinkedList();
312 
313                 for ( int i = docs.length - 1; i >= 0; i-- )
314                 {
315                     col.addAll( Arrays.asList( this.transformDocument( docs[i] ) ) );
316                 }
317 
318                 for ( final Iterator it = col.iterator(); it.hasNext(); )
319                 {
320                     final JaxpCurrency currency = (JaxpCurrency) it.next();
321                     if ( this.isoMap.put( currency.getIsoCode(), currency ) != null
322                          || ( currency.getDtausCode() != null
323                               && this.dtausMap.put( currency.getDtausCode(), currency ) != null ) )
324                     {
325                         throw new IllegalStateException( this.getDuplicateCurrencyMessage(
326                             this.getLocale(), currency.getIsoCode(),
327                             Currency.getInstance( currency.getIsoCode() ).getSymbol( this.getLocale() ) ) );
328 
329                     }
330                 }
331 
332                 this.getLogger().info( this.getCurrencyInfoMessage(
333                     this.getLocale(), new Integer( this.isoMap.size() ), new Integer( docs.length ) ) );
334 
335                 this.initialized = true;
336             }
337         }
338         catch ( final IOException e )
339         {
340             this.initialized = false;
341             throw new RuntimeException( e );
342         }
343         catch ( final SAXException e )
344         {
345             this.initialized = false;
346             throw new RuntimeException( e );
347         }
348         catch ( final ParserConfigurationException e )
349         {
350             this.initialized = false;
351             throw new RuntimeException( e );
352         }
353         catch ( final ParseException e )
354         {
355             this.initialized = false;
356             throw new RuntimeException( e );
357         }
358     }
359 
360     /**
361      * Checks configured properties.
362      *
363      * @throws PropertyException if properties hold invalid values.
364      */
365     private void assertValidProperties()
366     {
367         if ( this.getReloadIntervalMillis() < 0L )
368         {
369             throw new PropertyException( "reloadIntervalMillis", Long.toString( this.getReloadIntervalMillis() ) );
370         }
371         if ( this.getMonitoringThreshold() < 0L )
372         {
373             throw new PropertyException( "monitoringThreshold", Long.toString( this.getMonitoringThreshold() ) );
374         }
375     }
376 
377     /**
378      * Gets XML resources provided by any available {@code CurrenciesProvider} implementation.
379      *
380      * @return XML resources provided by any available {@code CurrenciesProvider} implementation.
381      *
382      * @throws IOException if retrieving resources fails.
383      *
384      * @see JaxpCurrenciesProvider
385      */
386     private URL[] getResources() throws IOException
387     {
388         final Collection resources = new HashSet();
389         final JaxpCurrenciesProvider[] provider = this.getCurrenciesProvider();
390 
391         for ( int i = provider.length - 1; i >= 0; i-- )
392         {
393             resources.addAll( Arrays.asList( provider[i].getResources() ) );
394         }
395 
396         return (URL[]) resources.toArray( new URL[ resources.size() ] );
397     }
398 
399     /**
400      * Adds a resource to the list of resources to monitor for changes.
401      *
402      * @param url The URL of the resource to monitor for changes.
403      *
404      * @throws NullPointerException if {@code url} is {@code null}.
405      */
406     private void monitorResource( final URL url )
407     {
408         if ( url == null )
409         {
410             throw new NullPointerException( "url" );
411         }
412 
413         try
414         {
415             final File file = new File( new URI( url.toString() ) );
416             this.monitorMap.put( file, new Long( file.lastModified() ) );
417             this.getLogger().info( this.getMonitoringInfoMessage( this.getLocale(), file.getAbsolutePath() ) );
418         }
419         catch ( final IllegalArgumentException e )
420         {
421             this.getLogger().info( this.getNotMonitoringWarningMessage(
422                 this.getLocale(), url.toExternalForm(), e.getMessage() ) );
423 
424         }
425         catch ( final URISyntaxException e )
426         {
427             this.getLogger().info( this.getNotMonitoringWarningMessage(
428                 this.getLocale(), url.toExternalForm(), e.getMessage() ) );
429 
430         }
431     }
432 
433     /**
434      * Parses all XML resources.
435      *
436      * @return The parsed documents.
437      *
438      * @see #getResources()
439      * @see #getDocumentBuilder()
440      *
441      * @throws IOException if retrieving resources fails.
442      * @throws ParserConfigurationException if configuring the XML parser fails.
443      * @throws SAXException if parsing fails.
444      */
445     private Document[] parseResources() throws IOException, ParserConfigurationException, SAXException
446     {
447         InputStream stream = null;
448 
449         final URL[] resources = this.getResources();
450         final Document[] ret = new Document[ resources.length ];
451 
452         if ( resources.length > 0 )
453         {
454             final DocumentBuilder validatingParser = this.getDocumentBuilder();
455             final DocumentBuilderFactory namespaceAwareFactory = DocumentBuilderFactory.newInstance();
456             namespaceAwareFactory.setNamespaceAware( true );
457             final DocumentBuilder nonValidatingParser = namespaceAwareFactory.newDocumentBuilder();
458 
459             final Task task = new Task();
460             task.setCancelable( false );
461             task.setDescription( new ReadsCurrenciesMessage() );
462             task.setIndeterminate( false );
463             task.setMaximum( resources.length - 1 );
464             task.setMinimum( 0 );
465             task.setProgress( 0 );
466 
467             try
468             {
469                 this.getTaskMonitor().monitor( task );
470 
471                 for ( int i = resources.length - 1; i >= 0; i-- )
472                 {
473                     task.setProgress( task.getMaximum() - i );
474 
475                     final URL resource = resources[i];
476                     final ErrorHandler errorHandler = new ErrorHandler()
477                     {
478 
479                         public void warning( final SAXParseException e ) throws SAXException
480                         {
481                             getLogger().warn( getParseExceptionMessage(
482                                 getLocale(), resource.toExternalForm(),
483                                 e.getMessage(), new Integer( e.getLineNumber() ),
484                                 new Integer( e.getColumnNumber() ) ) );
485 
486                         }
487 
488                         public void error( final SAXParseException e ) throws SAXException
489                         {
490                             throw new SAXException( getParseExceptionMessage(
491                                 getLocale(), resource.toExternalForm(),
492                                 e.getMessage(), new Integer( e.getLineNumber() ),
493                                 new Integer( e.getColumnNumber() ) ), e );
494 
495                         }
496 
497                         public void fatalError( final SAXParseException e ) throws SAXException
498                         {
499                             throw new SAXException( getParseExceptionMessage(
500                                 getLocale(), resource.toExternalForm(),
501                                 e.getMessage(), new Integer( e.getLineNumber() ),
502                                 new Integer( e.getColumnNumber() ) ), e );
503 
504                         }
505 
506                     };
507 
508                     nonValidatingParser.setErrorHandler( errorHandler );
509                     validatingParser.setErrorHandler( errorHandler );
510 
511                     try
512                     {
513                         this.monitorResource( resources[i] );
514                         stream = resources[i].openStream();
515                         ret[i] = nonValidatingParser.parse( stream );
516 
517                         if ( ret[i].getDocumentElement().hasAttributeNS( XSI_NS, "schemaLocation" ) )
518                         {
519                             stream.close();
520                             stream = resources[i].openStream();
521                             ret[i] = validatingParser.parse( stream );
522                         }
523                         else if ( this.getLogger().isInfoEnabled() )
524                         {
525                             this.getLogger().info( this.getNoSchemaLocationMessage(
526                                 this.getLocale(), resources[i].toExternalForm() ) );
527 
528                         }
529                     }
530                     finally
531                     {
532                         if ( stream != null )
533                         {
534                             stream.close();
535                             stream = null;
536                         }
537                     }
538                 }
539             }
540             finally
541             {
542                 this.getTaskMonitor().finish( task );
543             }
544         }
545         else
546         {
547             this.getLogger().warn( this.getNoCurrenciesFoundMessage( this.getLocale() ) );
548         }
549 
550         return ret;
551     }
552 
553     /**
554      * Transforms a XML document to the currency instances it contains.
555      *
556      * @param doc The document to transform.
557      *
558      * @return An array of the currency instances from the given document.
559      *
560      * @throws ParseException if parsing values fails.
561      */
562     private JaxpCurrency[] transformDocument( final Document doc ) throws ParseException
563     {
564         final Calendar cal = Calendar.getInstance();
565         final DateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd" );
566         final Collection col = new ArrayList( 500 );
567 
568         String modelVersion = null;
569         final String namespace = doc.getDocumentElement().getNamespaceURI();
570 
571         if ( namespace == null )
572         {
573             throw new RuntimeException( this.getUnsupportedNamespaceMessage( this.getLocale(), null ) );
574         }
575         else if ( CURRENCIES_NS.equals( namespace ) )
576         {
577             modelVersion = doc.getDocumentElement().getAttributeNS( namespace, "version" );
578         }
579         else if ( BANKING_NS.equals( namespace ) )
580         {
581             modelVersion = doc.getDocumentElement().getAttributeNS( namespace, "modelVersion" );
582         }
583         else
584         {
585             throw new RuntimeException( this.getUnsupportedNamespaceMessage( this.getLocale(), namespace ) );
586         }
587 
588         boolean supportedModelVersion = false;
589         for ( int i = SUPPORTED_VERSIONS.length - 1; i >= 0; i-- )
590         {
591             if ( SUPPORTED_VERSIONS[i].equals( modelVersion ) )
592             {
593                 supportedModelVersion = true;
594                 break;
595             }
596         }
597 
598         if ( !supportedModelVersion )
599         {
600             throw new RuntimeException( this.getUnsupportedModelVersionMessage( this.getLocale(), modelVersion ) );
601         }
602 
603         final NodeList l = doc.getDocumentElement().getElementsByTagNameNS( namespace, "currency" );
604 
605         for ( int i = l.getLength() - 1; i >= 0; i-- )
606         {
607             final Element e = (Element) l.item( i );
608 
609             if ( e.getParentNode().equals( doc.getDocumentElement() ) )
610             {
611                 final JaxpCurrency cur = new JaxpCurrency();
612                 cur.setIsoCode( e.getAttributeNS( namespace, "isoCode" ) );
613 
614                 if ( e.hasAttributeNS( namespace, "dtausCode" ) )
615                 {
616                     cur.setDtausCode( new Character( e.getAttributeNS( namespace, "dtausCode" ).charAt( 0 ) ) );
617                 }
618 
619                 cal.setTime( dateFormat.parse( e.getAttributeNS( namespace, "startDate" ) ) );
620                 cal.set( Calendar.HOUR_OF_DAY, 0 );
621                 cal.set( Calendar.MINUTE, 0 );
622                 cal.set( Calendar.SECOND, 0 );
623                 cal.set( Calendar.MILLISECOND, 0 );
624                 cur.setStartDate( cal.getTime() );
625 
626                 if ( e.hasAttributeNS( namespace, "endDate" ) )
627                 {
628                     cal.setTime( dateFormat.parse( e.getAttributeNS( namespace, "endDate" ) ) );
629                     cal.set( Calendar.HOUR_OF_DAY, 23 );
630                     cal.set( Calendar.MINUTE, 59 );
631                     cal.set( Calendar.SECOND, 59 );
632                     cal.set( Calendar.MILLISECOND, 999 );
633                     cur.setEndDate( cal.getTime() );
634                 }
635 
636                 col.add( cur );
637             }
638         }
639 
640         return (JaxpCurrency[]) col.toArray( new JaxpCurrency[ col.size() ] );
641     }
642 
643     /**
644      * Creates a new {@code DocumentBuilder} to use for parsing the XML resources.
645      * <p>This method tries to set the following JAXP property on the system's default XML parser:
646      * <ul>
647      * <li>{@code http://java.sun.com/xml/jaxp/properties/schemaLanguage} set to
648      * {@code http://www.w3.org/2001/XMLSchema}</li>
649      * </ul> When setting this property fails, a non-validating
650      * {@code DocumentBuilder} is returned and a warning message is logged.</p>
651      *
652      * @return A new {@code DocumentBuilder} to be used for parsing resources.
653      *
654      * @throws ParserConfigurationException if configuring the XML parser fails.
655      */
656     private DocumentBuilder getDocumentBuilder() throws ParserConfigurationException
657     {
658         final DocumentBuilder xmlBuilder;
659         final DocumentBuilderFactory xmlFactory = DocumentBuilderFactory.newInstance();
660         xmlFactory.setNamespaceAware( true );
661 
662         try
663         {
664             xmlFactory.setValidating( true );
665             xmlFactory.setAttribute( SCHEMA_LANGUAGE_KEY, SCHEMA_LANGUAGE );
666         }
667         catch ( final IllegalArgumentException e )
668         {
669             this.getLogger().info( this.getNoJAXPValidationWarningMessage( this.getLocale(), e.getMessage() ) );
670             xmlFactory.setValidating( false );
671         }
672 
673         xmlBuilder = xmlFactory.newDocumentBuilder();
674         xmlBuilder.setEntityResolver( new EntityResolverChain() );
675         return xmlBuilder;
676     }
677 
678     //--Constructors------------------------------------------------------------
679 
680 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausConstructors
681     // This section is managed by jdtaus-container-mojo.
682 
683     /** Standard implementation constructor <code>org.jdtaus.banking.ri.currencydir.JaxpCurrencyDirectory</code>. */
684     public JaxpCurrencyDirectory()
685     {
686         super();
687     }
688 
689 // </editor-fold>//GEN-END:jdtausConstructors
690 
691     //------------------------------------------------------------Constructors--
692     //--Dependencies------------------------------------------------------------
693 
694 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
695     // This section is managed by jdtaus-container-mojo.
696 
697     /**
698      * Gets the configured <code>Logger</code> implementation.
699      *
700      * @return The configured <code>Logger</code> implementation.
701      */
702     private Logger getLogger()
703     {
704         return (Logger) ContainerFactory.getContainer().
705             getDependency( this, "Logger" );
706 
707     }
708 
709     /**
710      * Gets the configured <code>CurrenciesProvider</code> implementation.
711      *
712      * @return The configured <code>CurrenciesProvider</code> implementation.
713      */
714     private JaxpCurrenciesProvider[] getCurrenciesProvider()
715     {
716         return (JaxpCurrenciesProvider[]) ContainerFactory.getContainer().
717             getDependency( this, "CurrenciesProvider" );
718 
719     }
720 
721     /**
722      * Gets the configured <code>TaskMonitor</code> implementation.
723      *
724      * @return The configured <code>TaskMonitor</code> implementation.
725      */
726     private TaskMonitor getTaskMonitor()
727     {
728         return (TaskMonitor) ContainerFactory.getContainer().
729             getDependency( this, "TaskMonitor" );
730 
731     }
732 
733     /**
734      * Gets the configured <code>Locale</code> implementation.
735      *
736      * @return The configured <code>Locale</code> implementation.
737      */
738     private Locale getLocale()
739     {
740         return (Locale) ContainerFactory.getContainer().
741             getDependency( this, "Locale" );
742 
743     }
744 
745 // </editor-fold>//GEN-END:jdtausDependencies
746 
747     //------------------------------------------------------------Dependencies--
748     //--Properties--------------------------------------------------------------
749 
750 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties
751     // This section is managed by jdtaus-container-mojo.
752 
753     /**
754      * Gets the value of property <code>defaultReloadIntervalMillis</code>.
755      *
756      * @return Default number of milliseconds to pass before resources are checked for modifications.
757      */
758     private java.lang.Long getDefaultReloadIntervalMillis()
759     {
760         return (java.lang.Long) ContainerFactory.getContainer().
761             getProperty( this, "defaultReloadIntervalMillis" );
762 
763     }
764 
765     /**
766      * Gets the value of property <code>defaultMonitoringThreshold</code>.
767      *
768      * @return Default number of currencies for which progress monitoring gets enabled.
769      */
770     private java.lang.Long getDefaultMonitoringThreshold()
771     {
772         return (java.lang.Long) ContainerFactory.getContainer().
773             getProperty( this, "defaultMonitoringThreshold" );
774 
775     }
776 
777 // </editor-fold>//GEN-END:jdtausProperties
778 
779     //--------------------------------------------------------------Properties--
780     //--Messages----------------------------------------------------------------
781 
782 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausMessages
783     // This section is managed by jdtaus-container-mojo.
784 
785     /**
786      * Gets the text of message <code>noJAXPValidationWarning</code>.
787      * <blockquote><pre>Keine JAXP Validierung verfügbar. {0}</pre></blockquote>
788      * <blockquote><pre>No JAXP validation available. {0}</pre></blockquote>
789      *
790      * @param locale The locale of the message instance to return.
791      * @param detailMessage format parameter.
792      *
793      * @return the text of message <code>noJAXPValidationWarning</code>.
794      */
795     private String getNoJAXPValidationWarningMessage( final Locale locale,
796             final java.lang.String detailMessage )
797     {
798         return ContainerFactory.getContainer().
799             getMessage( this, "noJAXPValidationWarning", locale,
800                 new Object[]
801                 {
802                     detailMessage
803                 });
804 
805     }
806 
807     /**
808      * Gets the text of message <code>notMonitoringWarning</code>.
809      * <blockquote><pre>{0} kann bei Änderung nicht automatisch neu geladen werden. {1}</pre></blockquote>
810      * <blockquote><pre>{0} cannot be monitored. {1}</pre></blockquote>
811      *
812      * @param locale The locale of the message instance to return.
813      * @param resourceName format parameter.
814      * @param detailMessage format parameter.
815      *
816      * @return the text of message <code>notMonitoringWarning</code>.
817      */
818     private String getNotMonitoringWarningMessage( final Locale locale,
819             final java.lang.String resourceName,
820             final java.lang.String detailMessage )
821     {
822         return ContainerFactory.getContainer().
823             getMessage( this, "notMonitoringWarning", locale,
824                 new Object[]
825                 {
826                     resourceName,
827                     detailMessage
828                 });
829 
830     }
831 
832     /**
833      * Gets the text of message <code>changeInfo</code>.
834      * <blockquote><pre>{0} aktualisiert.</pre></blockquote>
835      * <blockquote><pre>{0} changed.</pre></blockquote>
836      *
837      * @param locale The locale of the message instance to return.
838      * @param resourceName format parameter.
839      *
840      * @return the text of message <code>changeInfo</code>.
841      */
842     private String getChangeInfoMessage( final Locale locale,
843             final java.lang.String resourceName )
844     {
845         return ContainerFactory.getContainer().
846             getMessage( this, "changeInfo", locale,
847                 new Object[]
848                 {
849                     resourceName
850                 });
851 
852     }
853 
854     /**
855      * Gets the text of message <code>monitoringInfo</code>.
856      * <blockquote><pre>{0} wird bei Änderung automatisch neu geladen.</pre></blockquote>
857      * <blockquote><pre>Monitoring {0} for changes.</pre></blockquote>
858      *
859      * @param locale The locale of the message instance to return.
860      * @param resourceName format parameter.
861      *
862      * @return the text of message <code>monitoringInfo</code>.
863      */
864     private String getMonitoringInfoMessage( final Locale locale,
865             final java.lang.String resourceName )
866     {
867         return ContainerFactory.getContainer().
868             getMessage( this, "monitoringInfo", locale,
869                 new Object[]
870                 {
871                     resourceName
872                 });
873 
874     }
875 
876     /**
877      * Gets the text of message <code>parseException</code>.
878      * <blockquote><pre>Fehler bei der Verarbeitung der Resource "{0}" in Zeile {2}, Spalte {3}. {1}</pre></blockquote>
879      * <blockquote><pre>Error parsing resource "{0}" at line {2}, column {3}. {1}</pre></blockquote>
880      *
881      * @param locale The locale of the message instance to return.
882      * @param resourceName format parameter.
883      * @param cause format parameter.
884      * @param line format parameter.
885      * @param column format parameter.
886      *
887      * @return the text of message <code>parseException</code>.
888      */
889     private String getParseExceptionMessage( final Locale locale,
890             final java.lang.String resourceName,
891             final java.lang.String cause,
892             final java.lang.Number line,
893             final java.lang.Number column )
894     {
895         return ContainerFactory.getContainer().
896             getMessage( this, "parseException", locale,
897                 new Object[]
898                 {
899                     resourceName,
900                     cause,
901                     line,
902                     column
903                 });
904 
905     }
906 
907     /**
908      * Gets the text of message <code>unsupportedNamespace</code>.
909      * <blockquote><pre>Ungültiger XML-Namensraum {0}.</pre></blockquote>
910      * <blockquote><pre>Unsupported XML namespace {0}.</pre></blockquote>
911      *
912      * @param locale The locale of the message instance to return.
913      * @param namespace format parameter.
914      *
915      * @return the text of message <code>unsupportedNamespace</code>.
916      */
917     private String getUnsupportedNamespaceMessage( final Locale locale,
918             final java.lang.String namespace )
919     {
920         return ContainerFactory.getContainer().
921             getMessage( this, "unsupportedNamespace", locale,
922                 new Object[]
923                 {
924                     namespace
925                 });
926 
927     }
928 
929     /**
930      * Gets the text of message <code>unsupportedModelVersion</code>.
931      * <blockquote><pre>Keine Unterstützung für Modellversion {0}.</pre></blockquote>
932      * <blockquote><pre>Unsupported model version {0}.</pre></blockquote>
933      *
934      * @param locale The locale of the message instance to return.
935      * @param modelVersion format parameter.
936      *
937      * @return the text of message <code>unsupportedModelVersion</code>.
938      */
939     private String getUnsupportedModelVersionMessage( final Locale locale,
940             final java.lang.String modelVersion )
941     {
942         return ContainerFactory.getContainer().
943             getMessage( this, "unsupportedModelVersion", locale,
944                 new Object[]
945                 {
946                     modelVersion
947                 });
948 
949     }
950 
951     /**
952      * Gets the text of message <code>currencyInfo</code>.
953      * <blockquote><pre>{1,choice,0#Kein Dokument|1#Ein Dokument|1<{1} Dokumente} gelesen. {0,choice,0#Keine Währung|1#Eine Währung|1<{0} Währungen} verarbeitet.</pre></blockquote>
954      * <blockquote><pre>Read {1,choice,0#no document|1#one document|1<{1} documents}. Processed {0,choice,0#no entities|1#one entity|1<{0} entities}.</pre></blockquote>
955      *
956      * @param locale The locale of the message instance to return.
957      * @param entityCount format parameter.
958      * @param documentCount format parameter.
959      *
960      * @return the text of message <code>currencyInfo</code>.
961      */
962     private String getCurrencyInfoMessage( final Locale locale,
963             final java.lang.Number entityCount,
964             final java.lang.Number documentCount )
965     {
966         return ContainerFactory.getContainer().
967             getMessage( this, "currencyInfo", locale,
968                 new Object[]
969                 {
970                     entityCount,
971                     documentCount
972                 });
973 
974     }
975 
976     /**
977      * Gets the text of message <code>noSchemaLocation</code>.
978      * <blockquote><pre>Kein schemaLocation Attribut in Ressource "{0}". Keine Schema-Validierung.</pre></blockquote>
979      * <blockquote><pre>No schemaLocation attribute in resource "{0}". Schema validation skipped.</pre></blockquote>
980      *
981      * @param locale The locale of the message instance to return.
982      * @param resource format parameter.
983      *
984      * @return the text of message <code>noSchemaLocation</code>.
985      */
986     private String getNoSchemaLocationMessage( final Locale locale,
987             final java.lang.String resource )
988     {
989         return ContainerFactory.getContainer().
990             getMessage( this, "noSchemaLocation", locale,
991                 new Object[]
992                 {
993                     resource
994                 });
995 
996     }
997 
998     /**
999      * Gets the text of message <code>duplicateCurrency</code>.
1000      * <blockquote><pre>Währung {1} ({0}) ist mehrfach vorhanden.</pre></blockquote>
1001      * <blockquote><pre>Non-unique currency {1} ({0}).</pre></blockquote>
1002      *
1003      * @param locale The locale of the message instance to return.
1004      * @param currencyCode format parameter.
1005      * @param currencySymbol format parameter.
1006      *
1007      * @return the text of message <code>duplicateCurrency</code>.
1008      */
1009     private String getDuplicateCurrencyMessage( final Locale locale,
1010             final java.lang.String currencyCode,
1011             final java.lang.String currencySymbol )
1012     {
1013         return ContainerFactory.getContainer().
1014             getMessage( this, "duplicateCurrency", locale,
1015                 new Object[]
1016                 {
1017                     currencyCode,
1018                     currencySymbol
1019                 });
1020 
1021     }
1022 
1023     /**
1024      * Gets the text of message <code>noCurrenciesFound</code>.
1025      * <blockquote><pre>Keine Währungen gefunden.</pre></blockquote>
1026      * <blockquote><pre>No currencies found.</pre></blockquote>
1027      *
1028      * @param locale The locale of the message instance to return.
1029      *
1030      * @return the text of message <code>noCurrenciesFound</code>.
1031      */
1032     private String getNoCurrenciesFoundMessage( final Locale locale )
1033     {
1034         return ContainerFactory.getContainer().
1035             getMessage( this, "noCurrenciesFound", locale, null );
1036 
1037     }
1038 
1039 // </editor-fold>//GEN-END:jdtausMessages
1040 
1041     //----------------------------------------------------------------Messages--
1042 }