diff --git a/jOOQ-meta-extensions/src/main/java/org/jooq/util/ddl/DDLDatabase.java b/jOOQ-meta-extensions/src/main/java/org/jooq/util/ddl/DDLDatabase.java index bacfe58315..3797a3744b 100644 --- a/jOOQ-meta-extensions/src/main/java/org/jooq/util/ddl/DDLDatabase.java +++ b/jOOQ-meta-extensions/src/main/java/org/jooq/util/ddl/DDLDatabase.java @@ -47,6 +47,7 @@ import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Properties; @@ -65,6 +66,7 @@ import org.jooq.tools.JooqLogger; import org.jooq.tools.jdbc.JDBCUtils; import org.jooq.util.SchemaDefinition; import org.jooq.util.h2.H2Database; +import org.jooq.util.tools.FileComparator; import org.h2.api.ErrorCode; @@ -164,8 +166,14 @@ public class DDLDatabase extends H2Database { else if (file.isDirectory()) { log.info("Reading from: " + file); - for (File f : file.listFiles()) - load(encoding, f, pattern); + File[] files = file.listFiles(); + + if (files != null) { + Arrays.sort(files, FileComparator.INSTANCE); + + for (File f : files) + load(encoding, f, pattern); + } } } diff --git a/jOOQ-meta-extensions/src/main/java/org/jooq/util/tools/FileComparator.java b/jOOQ-meta-extensions/src/main/java/org/jooq/util/tools/FileComparator.java new file mode 100644 index 0000000000..7474635a7d --- /dev/null +++ b/jOOQ-meta-extensions/src/main/java/org/jooq/util/tools/FileComparator.java @@ -0,0 +1,76 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.util.tools; + +import java.io.File; +import java.util.Comparator; + +/** + * A comparator that compares file names semantically, just like the Windows + * Explorer. + *

+ * Desired semantic ordering: + * + *

+ * version-1
+ * version-2
+ * version-10
+ * 
+ *

+ * Undesired, lexicographic ordering: + * + *

+ * version-1
+ * version-10
+ * version-2
+ * 
+ * + * @author Lukas Eder + */ +public final class FileComparator implements Comparator { + + public static final FileComparator INSTANCE = new FileComparator(); + + @Override + public final int compare(File o1, File o2) { + String s1 = o1 == null ? null : o1.getName(); + String s2 = o2 == null ? null : o2.getName(); + + return FilenameComparator.INSTANCE.compare(s1, s2); + } +} diff --git a/jOOQ-meta-extensions/src/main/java/org/jooq/util/tools/FilenameComparator.java b/jOOQ-meta-extensions/src/main/java/org/jooq/util/tools/FilenameComparator.java new file mode 100644 index 0000000000..f655927c1c --- /dev/null +++ b/jOOQ-meta-extensions/src/main/java/org/jooq/util/tools/FilenameComparator.java @@ -0,0 +1,97 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.util.tools; + +import java.math.BigInteger; +import java.util.Comparator; +import java.util.regex.Pattern; + +/** + * A comparator that compares file names semantically, just like the Windows + * Explorer. + *

+ * Desired semantic ordering: + * + *

+ * version-1
+ * version-2
+ * version-10
+ * 
+ *

+ * Undesired, lexicographic ordering: + * + *

+ * version-1
+ * version-10
+ * version-2
+ * 
+ * + * @author Lukas Eder + */ +public final class FilenameComparator implements Comparator { + + // Idea taken from here: https://codereview.stackexchange.com/a/37217/5314 + private static final Pattern NUMBERS = Pattern.compile("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)"); + public static final FilenameComparator INSTANCE = new FilenameComparator(); + + @Override + public final int compare(String o1, String o2) { + if (o1 == null || o2 == null) + return o1 == null ? o2 == null ? 0 : -1 : 1; + + String[] split1 = NUMBERS.split(o1); + String[] split2 = NUMBERS.split(o2); + + for (int i = 0; i < Math.min(split1.length, split2.length); i++) { + char c1 = split1[i].charAt(0); + char c2 = split2[i].charAt(0); + int cmp = 0; + + if (c1 >= '0' && c1 <= '9' && c2 >= 0 && c2 <= '9') + cmp = new BigInteger(split1[i]).compareTo(new BigInteger(split2[i])); + + if (cmp == 0) + cmp = split1[i].compareTo(split2[i]); + + if (cmp != 0) + return cmp; + } + + return 0; + } +}