/*
 * 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.io.ArtifactManager;
import org.apache.sling.feature.io.ArtifactManagerConfig;
import org.apache.sling.feature.io.IOUtils;
import org.apache.sling.feature.io.json.FeatureJSONReader.SubstituteVariables;
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 java.io.File;
import java.io.FileReader;
import java.io.IOException;
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;

    @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());
    }

    @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(files1, files2);
    }

    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 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);

        String expectedFile = new File(getClass().getResource(expectedJSON).toURI()).getAbsolutePath();
        org.apache.sling.feature.Feature expected = IOUtils.getFeature(expectedFile, artifactManager, SubstituteVariables.NONE);
        org.apache.sling.feature.Feature actual = IOUtils.getFeature(outFile.getAbsolutePath(), artifactManager, SubstituteVariables.NONE);
        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, artifactManager);
        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, artifactManager);

        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, artifactManager);

        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);
    }

    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, artifactManager);
        }

        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);

        String expectedFile = new File(getClass().getResource(expectedJSON).toURI()).getAbsolutePath();
        org.apache.sling.feature.Feature expected = IOUtils.getFeature(expectedFile, artifactManager, SubstituteVariables.NONE);
        org.apache.sling.feature.Feature actual = IOUtils.getFeature(outFile.getAbsolutePath(), artifactManager, SubstituteVariables.NONE);
        assertFeaturesEqual(expected, actual);
    }

    public void testConvertToProvisioningModel(String originalJSON, String expectedProvModel) throws URISyntaxException, IOException {
        File inFile = new File(getClass().getResource(originalJSON).toURI());
        File outFile = new File(tempDir.toFile(), expectedProvModel + ".generated");

        FeatureToProvisioning.convert(inFile, outFile, artifactManager);

        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);
    }

    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);
    }

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

            FeatureToProvisioning.convert(inFile, outFile, artifactManager);
            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());

        assertFeatureKVMapEquals(expected.getVariables(), actual.getVariables());
        assertBundlesEqual(expected.getBundles(), actual.getBundles());
        assertConfigurationsEqual(expected.getConfigurations(), actual.getConfigurations(), expected.getBundles(), actual.getBundles());
        assertFeatureKVMapEquals(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;
                    assertFeatureKVMapEquals(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 Map<String, String> featureKvToMap(org.apache.sling.feature.KeyValueMap 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 assertFeatureKVMapEquals(org.apache.sling.feature.KeyValueMap expected,
            org.apache.sling.feature.KeyValueMap actual) {
        assertEquals(featureKvToMap(expected), featureKvToMap(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());
        }
    }
}
