001    /**
002     * Copyright 2004-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.apache.torque.mojo;
017    
018    import static org.apache.commons.io.FileUtils.forceMkdir;
019    
020    import java.io.File;
021    import java.io.FileInputStream;
022    import java.io.FileOutputStream;
023    import java.io.IOException;
024    import java.util.ArrayList;
025    import java.util.List;
026    
027    import org.apache.maven.plugin.MojoExecutionException;
028    import org.apache.torque.mojo.morph.DataMorpher;
029    import org.apache.torque.mojo.morph.MorphRequest;
030    import org.apache.torque.mojo.morph.Morpher;
031    import org.codehaus.plexus.util.DirectoryScanner;
032    import org.codehaus.plexus.util.StringUtils;
033    import org.kuali.core.db.torque.PrettyPrint;
034    import org.kuali.core.db.torque.Utils;
035    
036    /**
037     * Converts Ant impex data XML files into maven-impex-plugin data XML files
038     *
039     * @goal morphdata
040     * @phase generate-sources
041     */
042    public class MorphDataMojo extends BaseMojo {
043        Utils utils = new Utils();
044    
045        /**
046         * The artifactId (aka database schema)
047         *
048         * @parameter expression="${impex.artifactId}" default-value="${project.artifactId}"
049         * @required
050         */
051        private String artifactId;
052    
053        /**
054         * The directory in which the morphed XML will be generated.
055         *
056         * @parameter expression="${newDataOutputDir}" default-value="${project.build.directory}/generated-impex/xml"
057         * @required
058         */
059        private File newDataOutputDir;
060    
061        /**
062         * The directory containing the source (non-morphed) data XML files
063         *
064         * @parameter expression="${oldDataXMLDir}" default-value="${basedir}/src/main/impex"
065         * @required
066         */
067        private File oldDataXMLDir;
068    
069        /**
070         * The default set of files in that directory to include (ant style notation)
071         *
072         * @parameter expression="${oldDataXMLIncludes}" default-value="*.xml"
073         * @required
074         */
075        private String oldDataXMLIncludes;
076    
077        /**
078         * The default set of files in that directory to exclude (ant style notation)
079         *
080         * @parameter expression="${oldDataXMLExcludes}" default-value="schema.xml"
081         */
082        private String oldDataXMLExcludes;
083    
084        /**
085         * Use our configuration to determine the list of files we need to convert
086         */
087        protected String[] getOldFiles() throws IOException {
088            DirectoryScanner ds = new DirectoryScanner();
089            ds.setIncludes(new String[] { getOldDataXMLIncludes() });
090            if (getOldDataXMLExcludes() != null) {
091                ds.setExcludes(new String[] { getOldDataXMLExcludes() });
092            }
093            ds.setBasedir(getOldDataXMLDir());
094            ds.scan();
095            return ds.getIncludedFiles();
096        }
097    
098        protected boolean isMorphNeeded(final File oldFile, final File newFile) {
099            if (!newFile.exists()) {
100                return true;
101            }
102    
103            long lastModifiedOld = oldFile.lastModified();
104            long lastModifiedNew = newFile.lastModified();
105            return lastModifiedOld > lastModifiedNew;
106        }
107    
108        protected List<MorphRequest> getMorphRequests(final String[] oldFiles) throws IOException {
109            String inputPath = getOldDataXMLDir().getAbsolutePath();
110            String outputPath = getNewDataOutputDir().getAbsolutePath();
111            forceMkdir(getNewDataOutputDir());
112            List<MorphRequest> requests = new ArrayList<MorphRequest>();
113            for (String oldFilename : oldFiles) {
114                String oldFilePath = inputPath + FS + oldFilename;
115                String newFilePath = outputPath + FS + oldFilename;
116                File oldFile = new File(oldFilePath);
117                File newFile = new File(newFilePath);
118                if (!isMorphNeeded(oldFile, newFile)) {
119                    getLog().debug("Skipping morph on " + oldFilename);
120                    continue;
121                }
122                MorphRequest request = new MorphRequest();
123                request.setEncoding(getEncoding());
124                request.setName(oldFile.getName());
125                request.setInputStream(new FileInputStream(oldFile));
126                request.setOutputStream(new FileOutputStream(newFile));
127                requests.add(request);
128            }
129            return requests;
130        }
131    
132        protected void showConfig() {
133            getLog().info(StringUtils.repeat("-", utils.getDefaultPrintableConsoleWidth() - 7));
134            getLog().info("   From: " + oldDataXMLDir.getAbsolutePath());
135            getLog().info("     To: " + newDataOutputDir.getAbsolutePath());
136            getLog().info("Include: " + oldDataXMLIncludes);
137            getLog().info("Exclude: " + oldDataXMLExcludes);
138        }
139    
140        @Override
141        protected void executeMojo() throws MojoExecutionException {
142            try {
143                showConfig();
144                String[] oldFiles = getOldFiles();
145                PrettyPrint pp = new PrettyPrint("[INFO] Converting " + oldFiles.length + " data XML files");
146                utils.left(pp);
147                List<MorphRequest> requests = getMorphRequests(oldFiles);
148                for (MorphRequest request : requests) {
149                    Morpher morpher = new DataMorpher(request, artifactId);
150                    morpher.executeMorph();
151                }
152                utils.right(pp);
153                int skipCount = oldFiles.length - requests.size();
154                if (skipCount > 0) {
155                    getLog().info("Skipped " + skipCount + " files that were unchanged.");
156                }
157            } catch (IOException e) {
158                throw new MojoExecutionException("Unexpected error", e);
159            }
160        }
161    
162        public File getNewDataOutputDir() {
163            return newDataOutputDir;
164        }
165    
166        public void setNewDataOutputDir(final File newDataOutputDir) {
167            this.newDataOutputDir = newDataOutputDir;
168        }
169    
170        public File getOldDataXMLDir() {
171            return oldDataXMLDir;
172        }
173    
174        public void setOldDataXMLDir(final File oldDataXMLDir) {
175            this.oldDataXMLDir = oldDataXMLDir;
176        }
177    
178        public String getOldDataXMLIncludes() {
179            return oldDataXMLIncludes;
180        }
181    
182        public void setOldDataXMLIncludes(final String oldDataXMLIncludes) {
183            this.oldDataXMLIncludes = oldDataXMLIncludes;
184        }
185    
186        public String getOldDataXMLExcludes() {
187            return oldDataXMLExcludes;
188        }
189    
190        public void setOldDataXMLExcludes(final String oldDataXMLExcludes) {
191            this.oldDataXMLExcludes = oldDataXMLExcludes;
192        }
193    
194        public String getArtifactId() {
195            return artifactId;
196        }
197    
198        public void setArtifactId(String artifactId) {
199            this.artifactId = artifactId;
200        }
201    }