Coverage Report - liquibase.changelog.visitor.DBDocVisitor
 
Classes in this File Line Coverage Branch Coverage Complexity
DBDocVisitor
0%
0/81
0%
0/44
3.7
DBDocVisitor$1
N/A
N/A
3.7
DBDocVisitor$ChangeLogInfo
0%
0/14
0%
0/6
3.7
 
 1  
 package liquibase.changelog.visitor;
 2  
 
 3  
 import java.io.File;
 4  
 import java.io.FileOutputStream;
 5  
 import java.io.IOException;
 6  
 import java.io.InputStream;
 7  
 import java.util.ArrayList;
 8  
 import java.util.HashMap;
 9  
 import java.util.List;
 10  
 import java.util.Map;
 11  
 import java.util.Set;
 12  
 import java.util.SortedSet;
 13  
 import java.util.TreeSet;
 14  
 
 15  
 import liquibase.change.Change;
 16  
 import liquibase.changelog.ChangeSet;
 17  
 import liquibase.changelog.DatabaseChangeLog;
 18  
 import liquibase.database.Database;
 19  
 import liquibase.database.structure.Column;
 20  
 import liquibase.database.structure.DatabaseObject;
 21  
 import liquibase.database.structure.Table;
 22  
 import liquibase.dbdoc.AuthorListWriter;
 23  
 import liquibase.dbdoc.AuthorWriter;
 24  
 import liquibase.dbdoc.ChangeLogListWriter;
 25  
 import liquibase.dbdoc.ChangeLogWriter;
 26  
 import liquibase.dbdoc.ColumnWriter;
 27  
 import liquibase.dbdoc.HTMLWriter;
 28  
 import liquibase.dbdoc.PendingChangesWriter;
 29  
 import liquibase.dbdoc.PendingSQLWriter;
 30  
 import liquibase.dbdoc.RecentChangesWriter;
 31  
 import liquibase.dbdoc.TableListWriter;
 32  
 import liquibase.dbdoc.TableWriter;
 33  
 import liquibase.exception.DatabaseException;
 34  
 import liquibase.exception.DatabaseHistoryException;
 35  
 import liquibase.exception.LiquibaseException;
 36  
 import liquibase.resource.ResourceAccessor;
 37  
 import liquibase.snapshot.DatabaseSnapshot;
 38  
 import liquibase.snapshot.DatabaseSnapshotGeneratorFactory;
 39  
 import liquibase.util.StreamUtil;
 40  
 
 41  
 public class DBDocVisitor implements ChangeSetVisitor {
 42  
 
 43  
     private Database database;
 44  
 
 45  
     private SortedSet<ChangeLogInfo> changeLogs;
 46  
     private Map<DatabaseObject, List<Change>> changesByObject;
 47  
     private Map<String, List<Change>> changesByAuthor;
 48  
 
 49  
     private Map<DatabaseObject, List<Change>> changesToRunByObject;
 50  
     private Map<String, List<Change>> changesToRunByAuthor;
 51  
     private List<Change> changesToRun;
 52  
     private List<Change> recentChanges;
 53  
 
 54  
     private String rootChangeLogName;
 55  
     private DatabaseChangeLog rootChangeLog;
 56  
 
 57  
     private static final int MAX_RECENT_CHANGE = 50;
 58  
 
 59  0
     public DBDocVisitor(Database database) {
 60  0
         this.database = database;
 61  
 
 62  0
         changesByObject = new HashMap<DatabaseObject, List<Change>>();
 63  0
         changesByAuthor = new HashMap<String, List<Change>>();
 64  0
         changeLogs = new TreeSet<ChangeLogInfo>();
 65  
 
 66  0
         changesToRunByObject = new HashMap<DatabaseObject, List<Change>>();
 67  0
         changesToRunByAuthor = new HashMap<String, List<Change>>();
 68  0
         changesToRun = new ArrayList<Change>();
 69  0
         recentChanges = new ArrayList<Change>();
 70  0
     }
 71  
 
 72  
     @Override
 73  
     public ChangeSetVisitor.Direction getDirection() {
 74  0
         return ChangeSetVisitor.Direction.FORWARD;
 75  
     }
 76  
 
 77  
     @Override
 78  
     public void visit(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, Database database)
 79  
             throws LiquibaseException {
 80  0
         ChangeSet.RunStatus runStatus = this.database.getRunStatus(changeSet);
 81  0
         if (rootChangeLogName == null) {
 82  0
             rootChangeLogName = changeSet.getFilePath();
 83  
         }
 84  
 
 85  0
         if (rootChangeLog == null) {
 86  0
             this.rootChangeLog = databaseChangeLog;
 87  
         }
 88  
 
 89  0
         if (!changesByAuthor.containsKey(changeSet.getAuthor())) {
 90  0
             changesByAuthor.put(changeSet.getAuthor(), new ArrayList<Change>());
 91  
         }
 92  0
         if (!changesToRunByAuthor.containsKey(changeSet.getAuthor())) {
 93  0
             changesToRunByAuthor.put(changeSet.getAuthor(), new ArrayList<Change>());
 94  
         }
 95  
 
 96  0
         boolean toRun = runStatus.equals(ChangeSet.RunStatus.NOT_RAN)
 97  
                 || runStatus.equals(ChangeSet.RunStatus.RUN_AGAIN);
 98  0
         for (Change change : changeSet.getChanges()) {
 99  0
             if (toRun) {
 100  0
                 changesToRunByAuthor.get(changeSet.getAuthor()).add(change);
 101  0
                 changesToRun.add(change);
 102  
             } else {
 103  0
                 changesByAuthor.get(changeSet.getAuthor()).add(change);
 104  0
                 recentChanges.add(0, change);
 105  
             }
 106  
         }
 107  
 
 108  0
         ChangeLogInfo changeLogInfo = new ChangeLogInfo(changeSet.getFilePath(),
 109  
                 databaseChangeLog.getPhysicalFilePath());
 110  0
         if (!changeLogs.contains(changeLogInfo)) {
 111  0
             changeLogs.add(changeLogInfo);
 112  
         }
 113  
 
 114  0
         for (Change change : changeSet.getChanges()) {
 115  0
             Set<DatabaseObject> affectedDatabaseObjects = change.getAffectedDatabaseObjects(database);
 116  0
             if (affectedDatabaseObjects != null) {
 117  0
                 for (DatabaseObject dbObject : affectedDatabaseObjects) {
 118  0
                     if (toRun) {
 119  0
                         if (!changesToRunByObject.containsKey(dbObject)) {
 120  0
                             changesToRunByObject.put(dbObject, new ArrayList<Change>());
 121  
                         }
 122  0
                         changesToRunByObject.get(dbObject).add(change);
 123  
                     }
 124  
 
 125  0
                     if (!changesByObject.containsKey(dbObject)) {
 126  0
                         changesByObject.put(dbObject, new ArrayList<Change>());
 127  
                     }
 128  0
                     changesByObject.get(dbObject).add(change);
 129  
                 }
 130  
             }
 131  0
         }
 132  0
     }
 133  
 
 134  
     public void writeHTML(File rootOutputDir, ResourceAccessor resourceAccessor) throws IOException, DatabaseException,
 135  
             DatabaseHistoryException {
 136  0
         ChangeLogWriter changeLogWriter = new ChangeLogWriter(resourceAccessor, rootOutputDir);
 137  0
         HTMLWriter authorWriter = new AuthorWriter(rootOutputDir, database);
 138  0
         HTMLWriter tableWriter = new TableWriter(rootOutputDir, database);
 139  0
         HTMLWriter columnWriter = new ColumnWriter(rootOutputDir, database);
 140  0
         HTMLWriter pendingChangesWriter = new PendingChangesWriter(rootOutputDir, database);
 141  0
         HTMLWriter recentChangesWriter = new RecentChangesWriter(rootOutputDir, database);
 142  0
         HTMLWriter pendingSQLWriter = new PendingSQLWriter(rootOutputDir, database, rootChangeLog);
 143  
 
 144  0
         copyFile("liquibase/dbdoc/stylesheet.css", rootOutputDir);
 145  0
         copyFile("liquibase/dbdoc/index.html", rootOutputDir);
 146  0
         copyFile("liquibase/dbdoc/globalnav.html", rootOutputDir);
 147  0
         copyFile("liquibase/dbdoc/overview-summary.html", rootOutputDir);
 148  
 
 149  0
         DatabaseSnapshot snapshot = DatabaseSnapshotGeneratorFactory.getInstance().createSnapshot(database, null, null);
 150  
 
 151  0
         new ChangeLogListWriter(rootOutputDir).writeHTML(changeLogs);
 152  0
         new TableListWriter(rootOutputDir).writeHTML(new TreeSet<Object>(snapshot.getTables()));
 153  0
         new AuthorListWriter(rootOutputDir).writeHTML(new TreeSet<Object>(changesByAuthor.keySet()));
 154  
 
 155  0
         for (String author : changesByAuthor.keySet()) {
 156  0
             authorWriter.writeHTML(author, changesByAuthor.get(author), changesToRunByAuthor.get(author),
 157  
                     rootChangeLogName);
 158  
         }
 159  
 
 160  0
         for (Table table : snapshot.getTables()) {
 161  0
             tableWriter
 162  
                     .writeHTML(table, changesByObject.get(table), changesToRunByObject.get(table), rootChangeLogName);
 163  
         }
 164  
 
 165  0
         for (Column column : snapshot.getColumns()) {
 166  0
             columnWriter.writeHTML(column, changesByObject.get(column), changesToRunByObject.get(column),
 167  
                     rootChangeLogName);
 168  
         }
 169  
 
 170  0
         for (ChangeLogInfo changeLog : changeLogs) {
 171  0
             changeLogWriter.writeChangeLog(changeLog.logicalPath, changeLog.physicalPath);
 172  
         }
 173  
 
 174  0
         pendingChangesWriter.writeHTML("index", null, changesToRun, rootChangeLogName);
 175  0
         pendingSQLWriter.writeHTML("sql", null, changesToRun, rootChangeLogName);
 176  
 
 177  0
         if (recentChanges.size() > MAX_RECENT_CHANGE) {
 178  0
             recentChanges = recentChanges.subList(0, MAX_RECENT_CHANGE);
 179  
         }
 180  0
         recentChangesWriter.writeHTML("index", recentChanges, null, rootChangeLogName);
 181  
 
 182  0
     }
 183  
 
 184  
     private void copyFile(String fileToCopy, File rootOutputDir) throws IOException {
 185  0
         InputStream inputStream = getClass().getClassLoader().getResourceAsStream(fileToCopy);
 186  0
         FileOutputStream outputStream = null;
 187  
         try {
 188  0
             if (inputStream == null) {
 189  0
                 throw new IOException("Can not find " + fileToCopy);
 190  
             }
 191  0
             outputStream = new FileOutputStream(new File(rootOutputDir, fileToCopy.replaceFirst(".*\\/", "")), false);
 192  0
             StreamUtil.copy(inputStream, outputStream);
 193  
         } finally {
 194  0
             if (outputStream != null) {
 195  0
                 outputStream.close();
 196  
             }
 197  
         }
 198  0
     }
 199  
 
 200  0
     private static class ChangeLogInfo implements Comparable<ChangeLogInfo> {
 201  
         public String logicalPath;
 202  
         public String physicalPath;
 203  
 
 204  0
         private ChangeLogInfo(String logicalPath, String physicalPath) {
 205  0
             this.logicalPath = logicalPath;
 206  0
             this.physicalPath = physicalPath;
 207  0
         }
 208  
 
 209  
         @Override
 210  
         public boolean equals(Object o) {
 211  0
             if (this == o)
 212  0
                 return true;
 213  0
             if (o == null || getClass() != o.getClass())
 214  0
                 return false;
 215  
 
 216  0
             ChangeLogInfo that = (ChangeLogInfo) o;
 217  
 
 218  0
             return logicalPath.equals(that.logicalPath);
 219  
 
 220  
         }
 221  
 
 222  
         @Override
 223  
         public int hashCode() {
 224  0
             return logicalPath.hashCode();
 225  
         }
 226  
 
 227  
         @Override
 228  
         public int compareTo(ChangeLogInfo o) {
 229  0
             return this.logicalPath.compareTo(o.logicalPath);
 230  
         }
 231  
 
 232  
         @Override
 233  
         public String toString() {
 234  0
             return logicalPath;
 235  
         }
 236  
     }
 237  
 }