001/*
002 *  jDTAUS Banking RI CurrencyDirectory
003 *  Copyright (C) 2005 Christian Schulte
004 *  <cs@schulte.it>
005 *
006 *  This library is free software; you can redistribute it and/or
007 *  modify it under the terms of the GNU Lesser General Public
008 *  License as published by the Free Software Foundation; either
009 *  version 2.1 of the License, or any later version.
010 *
011 *  This library is distributed in the hope that it will be useful,
012 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 *  Lesser General Public License for more details.
015 *
016 *  You should have received a copy of the GNU Lesser General Public
017 *  License along with this library; if not, write to the Free Software
018 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
019 *
020 */
021package org.jdtaus.banking.ri.currencydir;
022
023import java.io.File;
024import java.io.IOException;
025import java.io.InputStream;
026import java.net.URI;
027import java.net.URISyntaxException;
028import java.net.URL;
029import java.text.DateFormat;
030import java.text.ParseException;
031import java.text.SimpleDateFormat;
032import java.util.ArrayList;
033import java.util.Arrays;
034import java.util.Calendar;
035import java.util.Collection;
036import java.util.Currency;
037import java.util.Date;
038import java.util.HashMap;
039import java.util.HashSet;
040import java.util.Iterator;
041import java.util.LinkedList;
042import java.util.Locale;
043import java.util.Map;
044import javax.xml.parsers.DocumentBuilder;
045import javax.xml.parsers.DocumentBuilderFactory;
046import javax.xml.parsers.ParserConfigurationException;
047import org.jdtaus.banking.messages.ReadsCurrenciesMessage;
048import org.jdtaus.banking.messages.SearchesCurrenciesMessage;
049import org.jdtaus.banking.spi.CurrencyMapper;
050import org.jdtaus.banking.spi.UnsupportedCurrencyException;
051import org.jdtaus.core.container.ContainerFactory;
052import org.jdtaus.core.container.PropertyException;
053import org.jdtaus.core.logging.spi.Logger;
054import org.jdtaus.core.monitor.spi.Task;
055import org.jdtaus.core.monitor.spi.TaskMonitor;
056import org.jdtaus.core.sax.util.EntityResolverChain;
057import org.w3c.dom.Document;
058import org.w3c.dom.Element;
059import org.w3c.dom.NodeList;
060import org.xml.sax.ErrorHandler;
061import org.xml.sax.SAXException;
062import org.xml.sax.SAXParseException;
063
064/**
065 * Currency directory implementation backed by XML resources.
066 * <p>This implementation uses XML resources provided by any available {@link JaxpCurrenciesProvider} implementation.
067 * Resources with a {@code file} URI scheme are monitored for changes by querying the last modification time. Monitoring
068 * is controlled by property {@code reloadIntervalMillis}.</p>
069 *
070 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
071 * @version $JDTAUS: JaxpCurrencyDirectory.java 8865 2014-01-10 17:13:42Z schulte $
072 */
073public class JaxpCurrencyDirectory implements CurrencyMapper
074{
075
076    /** JAXP configuration key to the Schema implementation attribute. */
077    private static final String SCHEMA_LANGUAGE_KEY = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
078
079    /** JAXP Schema implementation to use. */
080    private static final String SCHEMA_LANGUAGE = "http://www.w3.org/2001/XMLSchema";
081
082    /** jDTAUS {@code currencies} namespace URI. */
083    private static final String CURRENCIES_NS = "http://jdtaus.org/banking/xml/currencies";
084
085    /** jDTAUS {@code banking} namespace URI. */
086    private static final String BANKING_NS = "http://jdtaus.org/banking/model";
087
088    /** {@code http://www.w3.org/2001/XMLSchema-instance} namespace URI. */
089    private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
090
091    /** Version supported by this implementation. */
092    private static final String[] SUPPORTED_VERSIONS =
093    {
094        "1.0"
095    };
096
097    /** Flag indicating that initialization has been performed. */
098    private boolean initialized;
099
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}