/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You 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.
 */
package org.apache.sling.feature.modelconverter;

import org.apache.sling.feature.Bundles;
import org.apache.sling.feature.Configurations;
import org.apache.sling.feature.Extension;
import org.apache.sling.feature.ExtensionType;
import org.apache.sling.feature.Extensions;
import org.apache.sling.feature.builder.FeatureProvider;
import org.apache.sling.feature.io.file.ArtifactHandler;
import org.apache.sling.feature.io.file.ArtifactManager;
import org.apache.sling.feature.io.file.ArtifactManagerConfig;
import org.apache.sling.feature.io.json.FeatureJSONReader;
import org.apache.sling.provisioning.model.Artifact;
import org.apache.sling.provisioning.model.ArtifactGroup;
import org.apache.sling.provisioning.model.Configuration;
import org.apache.sling.provisioning.model.Feature;
import org.apache.sling.provisioning.model.KeyValueMap;
import org.apache.sling.provisioning.model.MergeUtility;
import org.apache.sling.provisioning.model.Model;
import org.apache.sling.provisioning.model.ModelConstants;
import org.apache.sling.provisioning.model.ModelUtility;
import org.apache.sling.provisioning.model.ModelUtility.ResolverOptions;
import org.apache.sling.provisioning.model.ModelUtility.VariableResolver;
import org.apache.sling.provisioning.model.RunMode;
import org.apache.sling.provisioning.model.Section;
import org.apache.sling.provisioning.model.io.ModelReader;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class ModelConverterTest {
    private Path tempDir;
    private ArtifactManager artifactManager;
    private FeatureProvider featureProvider;

    @Before
    public void setup() throws Exception {
        String tmpDir = System.getProperty("test.prov.files.tempdir");
        if (tmpDir != null) {
            tempDir = Paths.get(tmpDir);
            System.out.println("*** Using directory for generated files: " + tempDir);
        } else {
            tempDir = Files.createTempDirectory(getClass().getSimpleName());
        }
        artifactManager = ArtifactManager.getArtifactManager(
                new ArtifactManagerConfig());
        featureProvider =
            id -> {
                try {
                    File file = artifactManager.getArtifactHandler(id.toMvnUrl()).getFile();
                    try (Reader reader = new FileReader(file)) {
                        return FeatureJSONReader.read(reader, file.toURI().toURL().toString());
                    }
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            };
    }

    @After
    public void tearDown() throws Exception {
        if(System.getProperty("test.prov.files.tempdir") == null) {
            // Delete the temp dir again
            Files.walk(tempDir)
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .forEach(File::delete);
        }
    }

    @Test
    public void testBootToProvModel() throws Exception {
        testConvertToProvisioningModel("/boot.json", "/boot.txt");
    }

    @Test
    public void testBootToFeature() throws Exception {
        testConvertToFeature("/boot.txt", "/boot.json");
    }

    @Test
    public void testOakToProvModel() throws Exception {
        testConvertToProvisioningModel("/oak.json", "/oak.txt");
    }

    @Test
    public void testSeparateRunmodeFiles() throws Exception {
        testConvertToProvisioningModel(
            new String[] {
                    "/runmodeseparation/oak_no_runmode.json",
                    "/runmodeseparation/oak_mongo.json",
                    "/runmodeseparation/oak_tar.json"},
            "/oak.txt");
    }

    @Test
    public void testDifferentSourceIdenticalProvModel() throws Exception {
        String dir1 = System.getProperty("test.json.dir1");
        String dir2 = System.getProperty("test.json.dir2");

        File[] files1, files2;
        if (dir1 != null && dir2 != null) {
            files1 = new File(dir1).listFiles((d, n) -> n.endsWith(".json"));
            files2 = new File(dir2).listFiles((d, n) -> n.endsWith(".json"));
        } else {
            files1 = new File[] {
                  getFile("/runmodeseparation/oak_no_runmode.json"),
                  getFile("/runmodeseparation/oak_mongo.json"),
                  getFile("/runmodeseparation/oak_tar.json")
            };
            files2 = new File[] {getFile("/oak.json")};
        }

        testConvertToProvisioningModel(files2, files1);
    }

    private File getFile(String f) throws URISyntaxException {
        return new File(getClass().getResource(f).toURI());
    }

    @Test
    public void testOakToFeature() throws Exception {
        testConvertToFeature("/oak.txt", "/oak.json");
    }

    @Test
    public void testRepoinitToProvModel() throws Exception {
        testConvertToProvisioningModel("/repoinit.json", "/repoinit.txt");
    }

    @Test
    public void testRepoinitToFeature() throws Exception {
        testConvertToFeature("/repoinit.txt", "/repoinit.json");
    }

    @Test
    public void testLaunchpadToProvModel() throws Exception {
        testConvertToProvisioningModel("/launchpad.json", "/launchpad.txt");
    }

    @Test
    public void testLaunchpadToFeature() throws Exception {
        testConvertToFeature("/launchpad.txt", "/launchpad.json");
    }

    @Test
    public void testSimpleToProvModel() throws Exception {
        testConvertToProvisioningModel("/simple.json", "/simple.txt");
    }

    @Test
    public void testSimpleToFeature() throws Exception {
        testConvertToFeature("/simple.txt", "/simple.json");
    }

    @Test
    public void testSimpleInheritsToProvModel() throws Exception {
        testConvertToProvisioningModel("/simple_inherits.json", "/simple_inherits.txt", "/simple.json");
        testConvertToProvisioningModel("/simple_inherits.json", "/simple_inherits.txt", "/simple.json", "/simple_inherits.json");
    }

    @Test
    public void testSimpleInheritsViaMavenRepoToProvModel() throws Exception {
        artifactManager = Mockito.mock(ArtifactManager.class);
        Mockito.when(artifactManager.getArtifactHandler(Mockito.anyString())).then(new Answer<ArtifactHandler>() {
            @Override
            public ArtifactHandler answer(InvocationOnMock in) throws Throwable {
                String url = in.getArgument(0).toString();

                if (url.endsWith("simple_inherits.json")) {
                    return new ArtifactHandler(url, new File(url));
                } else if ("mvn:generated/simple/1.0.0".equals(url)) {
                    return new ArtifactHandler(url, new File(getClass().getResource("/simple.json").toURI()));
                }
                return null;
            }
        });

        testConvertToProvisioningModel("/simple_inherits.json", "/simple_inherits.txt");
    }

    @Test
    public void testSimple2ToProvModel() throws Exception {
        testConvertToProvisioningModel("/simple2.json", "/simple2.txt");
    }

    @Test
    public void testSimple2ToFeature() throws Exception {
        testConvertToFeature("/simple2.txt", "/simple2.json");
    }

    @Test
    public void testProvModelRoundtripFolder() throws Exception {
        String dir = System.getProperty("test.prov.files.dir");
        File filesDir;
        if (dir != null) {
            filesDir = new File(dir);
        } else {
            filesDir = new File(getClass().getResource("/repoinit.txt").toURI()).
                getParentFile();
        }

        for (File f : filesDir.listFiles((d, n) -> n.endsWith(".txt"))) {
            testConvertFromProvModelRoundTrip(f);
        }
    }

    @Test
    public void testModelGAV() throws Exception {
        String originalProvModel = "/boot.txt";
        String expectedJSON = "/boot_gav.json";

        File inFile = new File(getClass().getResource(originalProvModel).toURI());

        Map<String, Object> options = new HashMap<>();
        options.put("groupId", "testing123");
        options.put("version", "4.5.6");
        List<File> files = ProvisioningToFeature.convert(inFile, tempDir.toFile(), options);
        assertEquals("The testing code expects a single output file here", 1, files.size());
        File outFile = files.get(0);

        File expectedFile = new File(getClass().getResource(expectedJSON).toURI());
        org.apache.sling.feature.Feature expected = FeatureToProvisioning.getFeature(expectedFile);
        org.apache.sling.feature.Feature actual = FeatureToProvisioning.getFeature(outFile);
        assertFeaturesEqual(expected, actual);
    }

    @Test
    public void testConvertToProvisioningModelOverwriteLogic() throws Exception {
        String originalJSON = "/boot.json";
        String expectedProvModel = "/boot.txt";

        File inFile = new File(getClass().getResource(originalJSON).toURI());
        File outFile = new File(tempDir.toFile(), expectedProvModel + ".generated");

        FeatureToProvisioning.convert(inFile, outFile, featureProvider);
        List<String> orgLines = Files.readAllLines(outFile.toPath());
        assertNotEquals("Test precondition", "modified!", orgLines.get(orgLines.size() - 1));

        // Append to the output file:
        Files.write(outFile.toPath(), "\nmodified!".getBytes(), StandardOpenOption.APPEND);

        // Convert again and see that the output file is not modified
        FeatureToProvisioning.convert(inFile, outFile, featureProvider);

        List<String> lines = Files.readAllLines(outFile.toPath());
        assertEquals("modified!", lines.get(lines.size() - 1));

        // Modify the modification time of the generated file to be older than the input file
        outFile.setLastModified(inFile.lastModified() - 100000);
        FeatureToProvisioning.convert(inFile, outFile, featureProvider);

        List<String> owLines = Files.readAllLines(outFile.toPath());
        assertEquals("The file should have been overwritten since the source has modified since it's edit timestamp",
                orgLines, owLines);
    }

    @Test
    public void testConvertToFeature() throws Exception {
        File inFile = new File(getClass().getResource("/boot.txt").toURI());

        List<File> files = ProvisioningToFeature.convert(inFile, tempDir.toFile(), Collections.emptyMap());
        assertEquals("The testing code expects a single output file here", 1, files.size());
        File outFile = files.get(0);

        List<String> orgLines = Files.readAllLines(outFile.toPath());
        assertNotEquals("Test precondition", "modified!", orgLines.get(orgLines.size() - 1));

        // Append to the output file:
        Files.write(outFile.toPath(), "\nmodified!".getBytes(), StandardOpenOption.APPEND);

        // Convert again and see that the output file is not modified
        List<File> files2 = ProvisioningToFeature.convert(inFile, tempDir.toFile(), Collections.emptyMap());
        assertEquals("Should return the same file list", files, files2);

        List<String> lines = Files.readAllLines(outFile.toPath());
        assertEquals("modified!", lines.get(lines.size() - 1));

        // Modify the modification time of the generated file to be older than the input file
        outFile.setLastModified(inFile.lastModified() - 100000);
        List<File> files3 = ProvisioningToFeature.convert(inFile, tempDir.toFile(), Collections.emptyMap());
        assertEquals("Should return the same file list", files, files3);

        List<String> owLines = Files.readAllLines(outFile.toPath());
        assertEquals("The file should have been overwritten since the source has modified since it's edit timestamp",
                orgLines, owLines);
    }

    @Test
    public void testMultipleRepoinitSections() throws Exception {
        testConvertToFeature("/more/repoinit-multiple.txt", "/more/repoinit-multiple.json");
    }

    public void testConvertFromProvModelRoundTrip(File orgProvModel) throws Exception {
        System.out.println("*** Roundtrip converting: " + orgProvModel.getName());
        List<File> allGenerateProvisioningModelFiles = new ArrayList<>();

        List<File> generated = ProvisioningToFeature.convert(orgProvModel, tempDir.toFile(), Collections.emptyMap());

        for (File f : generated) {
            String baseName = f.getName().substring(0, f.getName().length() - ".json".length());
            assertFalse("File name cannot contain a colon", baseName.contains(":"));
            File genFile = new File(tempDir.toFile(), baseName + ".txt");
            allGenerateProvisioningModelFiles.add(genFile);
            FeatureToProvisioning.convert(f, genFile, featureProvider);
        }

        Model expected = readProvisioningModel(orgProvModel);
        Model actual = readProvisioningModel(allGenerateProvisioningModelFiles);
        assertModelsEqual(expected, actual);
    }

    public void testConvertToFeature(String originalProvModel, String expectedJSON) throws Exception {
        File inFile = new File(getClass().getResource(originalProvModel).toURI());

        List<File> files = ProvisioningToFeature.convert(inFile, tempDir.toFile(), Collections.emptyMap());
        assertEquals("The testing code expects a single output file here", 1, files.size());
        File outFile = files.get(0);

        File expectedFile = new File(getClass().getResource(expectedJSON).toURI());
        org.apache.sling.feature.Feature expected = FeatureToProvisioning.getFeature(expectedFile);
        org.apache.sling.feature.Feature actual = FeatureToProvisioning.getFeature(outFile);
        assertFeaturesEqual(expected, actual);
    }

    public void testConvertToProvisioningModel(String originalJSON, String expectedProvModel, String ... additionalContextFiles) throws URISyntaxException, IOException {
        File inFile = new File(getClass().getResource(originalJSON).toURI());
        File outFile = new File(tempDir.toFile(), expectedProvModel + ".generated");
        List<File> addFiles = new ArrayList<>();
        for (String af : additionalContextFiles) {
            addFiles.add(new File(getClass().getResource(af).toURI()));
        }

        FeatureToProvisioning.convert(inFile, outFile, featureProvider, addFiles.toArray(new File[] {}));

        File expectedFile = new File(getClass().getResource(expectedProvModel).toURI());
        Model expected = readProvisioningModel(expectedFile);
        Model actual = readProvisioningModel(outFile);
        assertModelsEqual(expected, actual);
    }

    public void testConvertToProvisioningModel(String [] jsonFiles, String expectedProvModel) throws URISyntaxException, IOException {
        List<File> inFiles = new ArrayList<>();
        for (String jf : jsonFiles) {
            inFiles.add(new File(getClass().getResource(jf).toURI()));
        }

        List<File> generatedFiles = convertFeatureFilesToProvisioningModel(inFiles.toArray(new File[] {}));

        File expectedFile = new File(getClass().getResource(expectedProvModel).toURI());
        Model expected = readProvisioningModel(expectedFile);
        Model actual = readProvisioningModel(generatedFiles);
        assertModelsEqual(expected, actual);
        assertModelsEqual(actual, expected);
    }

    public void testConvertToProvisioningModel(File[] jsonFiles1, File[] jsonFiles2) throws URISyntaxException, IOException {
        List<File> generatedFiles1 = convertFeatureFilesToProvisioningModel(jsonFiles1);
        List<File> generatedFiles2 = convertFeatureFilesToProvisioningModel(jsonFiles2);

        Model actual1 = readProvisioningModel(generatedFiles1);
        Model actual2 = readProvisioningModel(generatedFiles2);
        assertModelsEqual(actual1, actual2);
        assertModelsEqual(actual2, actual1);
    }

    private List<File> convertFeatureFilesToProvisioningModel(File[] jsonFiles) throws URISyntaxException, IOException {
        List<File> generatedFiles = new ArrayList<>();
        for (File inFile : jsonFiles) {
            File outFile;
            int counter = 0;
            do {
                outFile = new File(tempDir.toFile(), inFile.getName() + (counter++) + ".txt.generated");
            } while (outFile.exists());

            FeatureToProvisioning.convert(inFile, outFile, featureProvider);
            generatedFiles.add(outFile);
        }
        return generatedFiles;
    }

    private static Model readProvisioningModel(File modelFile) throws IOException {
        return readProvisioningModel(Collections.singletonList(modelFile));
    }

    private static Model readProvisioningModel(List<File> modelFiles) throws IOException {
        Model model = null;
        for (File modelFile : modelFiles) {
            try (FileReader fr = new FileReader(modelFile)) {
                Model nextModel = ModelReader.read(fr, modelFile.getAbsolutePath());

                if (model == null) {
                    model = nextModel;
                } else {
                    MergeUtility.merge(model, nextModel);
                }
            }
        }

        // Fix the configurations up from the internal format to the Dictionary-based format
        return ModelUtility.getEffectiveModel(model,
                new ResolverOptions().variableResolver(new VariableResolver() {
            @Override
            public String resolve(final Feature feature, final String name) {
                // Keep variables as-is in the model
                return "${" + name + "}";
            }
        }));
    }

    private void assertFeaturesEqual(org.apache.sling.feature.Feature expected, org.apache.sling.feature.Feature actual) {
        assertEquals(expected.getId(), actual.getId());
        assertEquals(expected.getTitle(), actual.getTitle());
        assertEquals(expected.getDescription(), actual.getDescription());
        assertEquals(expected.getVendor(), actual.getVendor());
        assertEquals(expected.getLicense(), actual.getLicense());

        assertEquals(expected.getVariables(), actual.getVariables());
        assertBundlesEqual(expected.getBundles(), actual.getBundles());
        assertConfigurationsEqual(expected.getConfigurations(), actual.getConfigurations(), expected.getBundles(), actual.getBundles());
        assertEquals(expected.getFrameworkProperties(), actual.getFrameworkProperties());
        assertExtensionEqual(expected.getExtensions(), actual.getExtensions());

        // Ignore caps and reqs, includes and here since they cannot come from the prov model.
    }

    private void assertBundlesEqual(Bundles expected, Bundles actual) {
        for (Iterator<org.apache.sling.feature.Artifact> it = expected.iterator(); it.hasNext(); ) {
            org.apache.sling.feature.Artifact ex = it.next();

            boolean found = false;
            for (Iterator<org.apache.sling.feature.Artifact> it2 = actual.iterator(); it2.hasNext(); ) {
                org.apache.sling.feature.Artifact ac = it2.next();
                if (ac.getId().equals(ex.getId())) {
                    found = true;
                    assertEquals(ex.getMetadata(), ac.getMetadata());
                    break;
                }
            }
            assertTrue("Not found: " + ex, found);
        }
    }

    private void assertConfigurationsEqual(Configurations expected, Configurations actual, Bundles exBundles, Bundles acBundles) {
        for (Iterator<org.apache.sling.feature.Configuration> it = expected.iterator(); it.hasNext(); ) {
            org.apache.sling.feature.Configuration ex = it.next();

            boolean found = false;
            for (Iterator<org.apache.sling.feature.Configuration> it2 = actual.iterator(); it2.hasNext(); ) {
                org.apache.sling.feature.Configuration ac = it2.next();
                if (ex.getPid() != null) {
                    if (ex.getPid().equals(ac.getPid())) {
                        found = true;
                        assertConfigProps(ex, ac, exBundles, acBundles);
                    }
                } else {
                    if (ex.getFactoryPid().equals(ac.getFactoryPid()) &&
                            ex.getName().equals(ac.getName())) {
                        found = true;
                        assertConfigProps(ex, ac, exBundles, acBundles);
                    }
                }
            }
            assertTrue(found);
        }
    }

    private void assertConfigProps(org.apache.sling.feature.Configuration expected, org.apache.sling.feature.Configuration actual, Bundles exBundles, Bundles acBundles) {
        assertTrue("Configurations not equal: " + expected.getProperties() + " vs " + actual.getProperties(),
                configPropsEqual(expected.getProperties(), actual.getProperties()));
    }

    private boolean configPropsEqual(Dictionary<String, Object> d1, Dictionary<String, Object> d2) {
        if (d1.size() != d2.size()) {
            return false;
        }

        for (Enumeration<String> e = d1.keys(); e.hasMoreElements(); ) {
            String k = e.nextElement();
            Object v = d1.get(k);
            if (v instanceof Object[]) {
                if (!Arrays.equals((Object[]) v, (Object[]) d2.get(k)))
                    return false;
            } else {
                if (!v.equals(d2.get(k)))
                    return false;
            }
        }
        return true;
    }

    private void assertModelsEqual(Model expected, Model actual) {
        for (int i=0; i<expected.getFeatures().size(); i++) {
            Feature expectedFeature = expected.getFeatures().get(i);
            Feature actualFeature = actual.getFeatures().get(i);
            assertFeaturesEqual(expectedFeature, actualFeature);
        }
    }

    private void assertFeaturesEqual(Feature expected, Feature actual) {
        assertEquals(expected.getName(), actual.getName());
        assertEquals(expected.getVersion(), actual.getVersion());
        assertEquals(expected.getType(), actual.getType());
        assertRunModesEqual(expected.getName(), expected.getRunModes(), actual.getRunModes());
        assertKVMapEquals(expected.getVariables(), actual.getVariables());
        assertSectionsEqual(expected.getAdditionalSections(), actual.getAdditionalSections());
    }

    private void assertRunModesEqual(String featureName, List<RunMode> expected, List<RunMode> actual) {
        assertEquals(expected.size(), actual.size());
        for (RunMode rm : expected) {
            boolean found = false;
            for (RunMode arm : actual) {
                if (runModesEqual(featureName, rm, arm)) {
                    found = true;
                    break;
                }

            }
            if (!found) {
                fail("Run Mode " + rm + " not found in actual list " + actual);
            }
        }
    }

    private boolean runModesEqual(String featureName, RunMode rm1, RunMode rm2) {
        if (rm1.getNames() == null) {
            if (rm2.getNames() != null)
                return false;
        } else {
            if (rm2.getNames() == null)
                return false;

            HashSet<String> names1 = new HashSet<>(Arrays.asList(rm1.getNames()));
            HashSet<String> names2 = new HashSet<>(Arrays.asList(rm2.getNames()));

            if (!names1.equals(names2))
                return false;
        }

        List<ArtifactGroup> ag1 = rm1.getArtifactGroups();
        List<ArtifactGroup> ag2 = rm2.getArtifactGroups();
        if (ag1.size() != ag2.size())
            return false;

        for (ArtifactGroup g1 : ag1) {
            boolean found = false;
            for (ArtifactGroup g2 : ag2) {
                if (artifactGroupsEquals(featureName, g1, g2)) {
                    found = true;
                    break;
                }
            }
            if (!found)
                return false;
        }

        List<Configuration> configs1 = new ArrayList<>();
        rm1.getConfigurations().iterator().forEachRemaining(configs1::add);
        List<Configuration> configs2 = new ArrayList<>();
        rm2.getConfigurations().iterator().forEachRemaining(configs2::add);
        if (configs1.size() != configs2.size())
            return false;

        for (int i=0; i < configs1.size(); i++) {
            Configuration cfg1 = configs1.get(i);

            boolean found = false;
            for (Configuration cfg2 : configs2) {
                if (cfg1.getFactoryPid() == null) {
                    if (cfg2.getFactoryPid() != null) {
                        continue;
                    }
                } else if (!cfg1.getFactoryPid().equals(cfg2.getFactoryPid())) {
                    continue;
                }

                if (!cfg1.getPid().equals(cfg2.getPid())) {
                    continue;
                }

                // Factory and ordinary PIDs are equal, so check the content
                found = true;

                if (!configPropsEqual(cfg1.getProperties(), cfg2.getProperties())) {
                    return false;
                }

                break;
            }
            if (!found) {
                // Configuration with this PID not found
                return false;
            }
        }

        Map<String, String> m1 = kvToMap(rm1.getSettings());
        Map<String, String> m2 = kvToMap(rm2.getSettings());

        return m1.equals(m2);
    }

    private Map<String, String> kvToMap(KeyValueMap<String> kvm) {
        Map<String, String> m = new HashMap<>();

        for (Map.Entry<String, String> entry : kvm) {
            m.put(entry.getKey(), entry.getValue());
        }

        return m;
    }

    private boolean artifactGroupsEquals(String featureName, ArtifactGroup g1, ArtifactGroup g2) {
        int sl1 = effectiveStartLevel(featureName, g1.getStartLevel());
        int sl2 = effectiveStartLevel(featureName, g2.getStartLevel());
        if (sl1 != sl2)
            return false;

        List<Artifact> al1 = new ArrayList<>();
        g1.iterator().forEachRemaining(al1::add);

        List<Artifact> al2 = new ArrayList<>();
        g2.iterator().forEachRemaining(al2::add);

        for (int i=0; i<al1.size(); i++) {
            Artifact a1 = al1.get(i);
            boolean found = false;
            for (Iterator<Artifact> it = al2.iterator(); it.hasNext(); ) {
                Artifact a2 = it.next();
                if (a1.compareTo(a2) == 0) {
                    found = true;
                    it.remove();
                }
            }
            if (!found) {
                return false;
            }
        }

        // Should have found all artifacts
        return (al2.size() == 0);
    }

    private int effectiveStartLevel(String featureName, int startLevel) {
        if (startLevel != 0)
            return startLevel;

        if (ModelConstants.FEATURE_BOOT.equals(featureName)) {
            return 1;
        } else {
            return 20;
        }
    }

    private void assertKVMapEquals(KeyValueMap<String> expected, KeyValueMap<String> actual) {
        assertEquals(kvToMap(expected), kvToMap(actual));
    }

    private void assertExtensionEqual(Extensions expected, Extensions actual) {
        assertEquals(expected.size(), actual.size());

        for (int i=0; i<expected.size(); i++) {
            // TODO support the fact that they may be out of order
            Extension ex = expected.get(i);
            Extension ac = actual.get(i);

            assertEquals(ex.getType(), ac.getType());
            assertEquals(ex.getName(), ac.getName());
            assertEquals(ex.isRequired(), ac.isRequired());

            if (ex.getType() == ExtensionType.TEXT) {
                String exTxt = ex.getText().replaceAll("\\s+", "");
                String acTxt = ac.getText().replaceAll("\\s+", "");
                assertEquals(exTxt, acTxt);
            } else if (ex.getType() == ExtensionType.JSON) {
                String exJson = ex.getJSON().replaceAll("\\s+", "").replaceAll("\"\",", "");
                String acJson = ac.getJSON().replaceAll("\\s+", "").replaceAll("\"\",", "");
                assertEquals(exJson, acJson);
            }

            /* TODO reinstantiate for Artifacts extentions
            assertEquals(ex.getArtifacts().size(), ac.getArtifacts().size());
            for (int j = 0; j<ex.getArtifacts().size(); j++) {
                org.apache.sling.feature.Artifact exa = ex.getArtifacts().get(j);
                org.apache.sling.feature.Artifact aca = ac.getArtifacts().get(j);
                assertEquals(exa.getId().toMvnId(), aca.getId().toMvnId());
            }
            */
        }
    }

    private void assertSectionsEqual(List<Section> expected, List<Section> actual) {
        assertEquals(expected.size(), actual.size());

        for (int i=0; i<expected.size(); i++) {
            Section esec = expected.get(i);
            Section asec = actual.get(i);
            assertEquals(esec.getName(), asec.getName());
            assertEquals(esec.getContents().replaceAll("\\s+", ""),
                    asec.getContents().replaceAll("\\s+", ""));
            assertEquals(esec.getAttributes(), asec.getAttributes());
        }
    }
}
