[CALCITE-1036] DiffRepository should not insert new resources at the end of the repository
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/8bc5f853 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/8bc5f853 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/8bc5f853 Branch: refs/heads/master Commit: 8bc5f8538f5c284e93ddc4ecfb59dab9458117f7 Parents: 9a52b5e Author: Julian Hyde <[email protected]> Authored: Wed Dec 23 16:18:22 2015 -0800 Committer: Julian Hyde <[email protected]> Committed: Sun Jan 10 00:51:24 2016 -0800 ---------------------------------------------------------------------- .../org/apache/calcite/test/DiffRepository.java | 54 +++++++++++++++++--- 1 file changed, 47 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/8bc5f853/core/src/test/java/org/apache/calcite/test/DiffRepository.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/DiffRepository.java b/core/src/test/java/org/apache/calcite/test/DiffRepository.java index 78dcc10..90ecc83 100644 --- a/core/src/test/java/org/apache/calcite/test/DiffRepository.java +++ b/core/src/test/java/org/apache/calcite/test/DiffRepository.java @@ -17,6 +17,7 @@ package org.apache.calcite.test; import org.apache.calcite.avatica.util.Spaces; +import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; import org.apache.calcite.util.XmlOutput; @@ -302,7 +303,7 @@ public class DiffRepository { private synchronized String get( final String testCaseName, String resourceName) { - Element testCaseElement = getTestCaseElement(testCaseName, true); + Element testCaseElement = getTestCaseElement(testCaseName, true, null); if (testCaseElement == null) { if (baseRepository != null) { return baseRepository.get(testCaseName, resourceName); @@ -355,17 +356,18 @@ public class DiffRepository { */ private synchronized Element getTestCaseElement( final String testCaseName, - boolean checkOverride) { + boolean checkOverride, + List<Pair<String, Element>> elements) { final NodeList childNodes = root.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node child = childNodes.item(i); if (child.getNodeName().equals(TEST_CASE_TAG)) { Element testCase = (Element) child; - if (testCaseName.equals( - testCase.getAttribute(TEST_CASE_NAME_ATTR))) { + final String name = testCase.getAttribute(TEST_CASE_NAME_ATTR); + if (testCaseName.equals(name)) { if (checkOverride && (baseRepository != null) - && (baseRepository.getTestCaseElement(testCaseName, false) != null) + && (baseRepository.getTestCaseElement(testCaseName, false, null) != null) && !"true".equals( testCase.getAttribute(TEST_CASE_OVERRIDES_ATTR))) { throw new RuntimeException( @@ -375,6 +377,9 @@ public class DiffRepository { } return testCase; } + if (elements != null) { + elements.add(Pair.of(name, testCase)); + } } } return null; @@ -456,11 +461,13 @@ public class DiffRepository { String testCaseName, String resourceName, String value) { - Element testCaseElement = getTestCaseElement(testCaseName, true); + final List<Pair<String, Element>> map = new ArrayList<>(); + Element testCaseElement = getTestCaseElement(testCaseName, true, map); if (testCaseElement == null) { testCaseElement = doc.createElement(TEST_CASE_TAG); testCaseElement.setAttribute(TEST_CASE_NAME_ATTR, testCaseName); - root.appendChild(testCaseElement); + Node refElement = ref(testCaseName, map); + root.insertBefore(testCaseElement, refElement); } Element resourceElement = getResourceElement(testCaseElement, resourceName, true); @@ -479,6 +486,39 @@ public class DiffRepository { flushDoc(); } + private Node ref(String testCaseName, List<Pair<String, Element>> map) { + if (map.isEmpty()) { + return null; + } + // Compute the position that the new element should be if the map were + // sorted. + int i = 0; + final List<String> names = Pair.left(map); + for (String s : names) { + if (s.compareToIgnoreCase(testCaseName) <= 0) { + ++i; + } + } + // Starting at a proportional position in the list, + // move forwards through lesser names, then + // move backwards through greater names. + // + // The intended effect is that if the list is already sorted, the new item + // will end up in exactly the right position, and if the list is not sorted, + // the new item will end up in approximately the right position. + while (i < map.size() + && names.get(i).compareToIgnoreCase(testCaseName) < 0) { + ++i; + } + if (i >= map.size() - 1) { + return null; + } + while (i >= 0 && names.get(i).compareToIgnoreCase(testCaseName) > 0) { + --i; + } + return map.get(i + 1).right; + } + /** * Flushes the reference document to the file system. */
