001    package org.andromda.translation.ocl.testsuite;
002    
003    import java.io.File;
004    import java.net.URL;
005    import java.util.Arrays;
006    import java.util.LinkedHashMap;
007    import java.util.List;
008    import java.util.Map;
009    import org.andromda.core.common.XmlObjectFactory;
010    import org.apache.commons.lang.StringUtils;
011    import org.apache.log4j.Logger;
012    
013    
014    /**
015     * Finds all translation tests from the current base directory up.
016     *
017     * @author Chad Brandon
018     */
019    public class TranslationTestDiscoverer
020    {
021        private static final Logger logger = Logger.getLogger(TranslationTestDiscoverer.class);
022    
023        /**
024         * This is the prefix of translation tests, each translation test must start with this in order to be found.
025         */
026        private static final String TEST_PREFIX = "TranslationTest-";
027    
028        /**
029         * Names of ignored files when file.isDirectory()
030         */
031        private static final List<String> IGNORED_DIRECTORIES = Arrays.asList("CVS", ".svn");
032    
033        /**
034         * Stores the discovered translation tests.
035         */
036        private Map<String, TranslationTest> translationTests = new LinkedHashMap<String, TranslationTest>();
037    
038        /**
039         * The shared instance
040         */
041        private static TranslationTestDiscoverer instance;
042    
043        /**
044         * Gets the shared instance of this TranslationTestDiscoverer.
045         *
046         * @return the shared TranslationTestDiscoverer.
047         */
048        public static TranslationTestDiscoverer instance()
049        {
050            if (instance == null)
051            {
052                instance = new TranslationTestDiscoverer();
053            }
054            return instance;
055        }
056    
057        /**
058         * This method discovers all translation tests within the given <code>directory</code>.
059         * @param directory
060         */
061        public void discoverTests(final String directory)
062        {
063            if (StringUtils.isBlank(directory))
064            {
065                throw new TranslationTestDiscovererException("The 'directory' " +
066                        " was not specified, please specify this value with the location from which to" +
067                        " begin the discovery of translation test files");
068            }
069            if (this.translationTests.isEmpty())
070            {
071                this.discoverTests(new File(directory));
072            }
073        }
074    
075        /**
076         * This method discovers all translation tests within the <code>currentDirectory</code>, it travels down the
077         * directory structure looking for files that have a prefix of 'TranslationTest-'.
078         */
079        private void discoverTests(final File currentDirectory)
080        {
081            try
082            {
083                final String[] files = currentDirectory.list();
084                if (files == null || files.length == 0)
085                {
086                    if (logger.isDebugEnabled())
087                    {
088                        logger.debug("no files or directories found in directory '" + currentDirectory + '\'');
089                    }
090                } else
091                {
092                    for (String filename : files)
093                    {
094                        File file = new File(currentDirectory, filename);
095                        if (StringUtils.trimToEmpty(file.getName()).startsWith(TEST_PREFIX))
096                        {
097                            final URL testUrl = file.toURI().toURL();
098                            if (logger.isInfoEnabled())
099                            {
100                                logger.info("found translation test --> '" + testUrl + '\'');
101                            }
102    
103                            TranslationTest test =
104                                    (TranslationTest) XmlObjectFactory.getInstance(TranslationTest.class).getObject(testUrl);
105                            test.setUri(testUrl);
106                            this.translationTests.put(
107                                    test.getTranslation(),
108                                    test);
109                        } else if (file.isDirectory() && !IGNORED_DIRECTORIES.contains(file.getName()))
110                        {
111                            this.discoverTests(file);
112                        }
113                    }
114                }
115            }
116            catch (final Throwable throwable)
117            {
118                logger.error(throwable);
119                throw new TranslationTestDiscovererException(throwable);
120            }
121        }
122    
123        /**
124         * Returns the TranslationTest for the given <code>translation</code> (if one can be found), otherwise returns
125         * null.
126         *
127         * @param translation the name of the translation
128         * @return TranslationTest
129         */
130        public TranslationTest getTest(String translation)
131        {
132            return this.translationTests.get(StringUtils.trimToEmpty(translation));
133        }
134    
135        /**
136         * Returns the discovered translation tests keyed by <code>translation<code>.
137         * @return translationTests
138         */
139        public Map<String, TranslationTest> getTests()
140        {
141            return this.translationTests;
142        }
143    
144        /**
145         * Shuts down this instance and releases any resources.
146         */
147        public void shutdown()
148        {
149            this.translationTests.clear();
150            TranslationTestDiscoverer.instance = null;
151        }
152    }