package be.iminds.ilabt.jfed.rspec.model;

import be.iminds.ilabt.jfed.lowlevel.api.user_spec.UserSpec;
import be.iminds.ilabt.jfed.rspec.model.impl.BasicRspecFactory;
import be.iminds.ilabt.jfed.rspec.parser.StaxRspecParser;
import be.iminds.ilabt.jfed.rspec.parser.StringExtraXml;
import be.iminds.ilabt.jfed.rspec.parser.TestRspecReconstructable;
import be.iminds.ilabt.jfed.rspec.parser.TestRspecsLibrary;
import be.iminds.ilabt.jfed.util.GeniUrn;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static org.testng.Assert.*;


/**
 * TestRspec with BasicRspecFactory
 */
public class TestRspec  {
    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(TestRspec.class);

    protected static final String TEST_COMP_MAN_URN = "urn:publicid:IDN+example.com+authority+cm";
    protected static final String TEST_COMP_MAN_URN2 = "urn:publicid:IDN+example.net+authority+cm";

    protected static final String TEST_USER_URN1 = "urn:publicid:IDN+example.com+user+foo";
    protected static final String TEST_USER_URN2 = "urn:publicid:IDN+example.net+user+bar";

    protected static final String TEST_USER_SSHKEY1 = "ssh-dsa dummykey";
    protected static final String TEST_USER_SSHKEY2 = "ssh-rsa someotherkey";
    protected static final String TEST_USER_SSHKEY3 = "ssh-rsa foobar";
    protected static final String TEST_USER_SSHKEY4 = "ssh-rsa foobarbaz";

    protected final RspecFactory rspecFactory;

    protected TestRspec(RspecFactory rspecFactory) {
        this.rspecFactory = rspecFactory;
    }
    public TestRspec() {
        this(BasicRspecFactory.getInstance());
    }

    public ModelRspec generateBaseTestRspec(RspecFactory rspecFactory) {
        ModelRspec testRspec = rspecFactory.createModelRspec("request");
        RspecNode n1 = rspecFactory.createNodeWithClientId(testRspec, "firstNode");
        testRspec.addNode(n1);
        RspecNode n2 = rspecFactory.createNodeWithClientId(testRspec, "secondNode");
        testRspec.addNode(n2);
        RspecNode n3 = rspecFactory.createNodeWithClientId(testRspec, "thirdNode");
        testRspec.addNode(n3);
        RspecNode n4 = rspecFactory.createNodeWithClientId(testRspec, testRspec.nextNodeName());
        testRspec.addNode(n4);

        n1.setSliverType(new SliverTypeBuilder("raw-pc").addDiskImage("DUMMY").build());
        n2.setSliverType(new SliverTypeBuilder("raw-pc").addDiskImage("DUMMY").build());
        n3.setSliverType(new SliverTypeBuilder("raw-pc").addDiskImage("DUMMY").build());
        n4.setSliverType(new SliverTypeBuilder("raw-pc").addDiskImage("DUMMY").build());

        n1.setComponentManagerId(TEST_COMP_MAN_URN);
        n1.setComponentId(TEST_COMP_MAN_URN2);
        n1.setExclusive(true);

        RspecLink l1 = rspecFactory.createLinkWithClientId(testRspec, "link1", "lan");
        RspecInterface i1 = rspecFactory.createInterface(n1, l1, testRspec.nextIfaceName(n1));
        RspecInterface i2 = rspecFactory.createInterface(n2, l1, testRspec.nextIfaceName(n2));
        RspecInterface i3 = rspecFactory.createInterface(n3, l1, testRspec.nextIfaceName(n3));
        i1.setClientId("if1");
        i2.setClientId("if2");
        i3.setClientId("if3");

        testRspec.addLink(l1);

        RspecLink l2 = rspecFactory.createLinkWithClientId(testRspec, testRspec.nextLinkName(), "lan");
        RspecInterface i4 = rspecFactory.createInterface(n1, l2, testRspec.nextIfaceName(n1));
        RspecInterface i5 = rspecFactory.createInterface(n4, l2, testRspec.nextIfaceName(n4));
        l2.setClientId("gigalink2");
        testRspec.addLink(l2);

        return testRspec;
    }

    /**
     * Test if the basic settings are ok.
     *
     * Useful to call in each test, to see if some features leaves the basic settings intact.
     *
     * @param rspecModel
     */
    protected void testBasics(ModelRspec rspecModel) {
        RspecNode n1 = rspecModel.getNodeByClientId("firstNode");
        assertNotNull(n1);
        assertEquals(n1.getComponentManagerId().getValue(), TEST_COMP_MAN_URN, "ns component_manager_urn is not equal");
        assertEquals(n1.getComponentId().getValue(), TEST_COMP_MAN_URN2);
        assertEquals(n1.getExclusive(), Boolean.TRUE);
        assertEquals(n1.getOsImageUrn(), "DUMMY");
        assertEquals(n1.getSliverTypeName(), "raw-pc");

        RspecNode n2 = rspecModel.getNodeByClientId("secondNode");
        assertNotNull(n2);
//        assertEquals(n2.getExclusive(), Boolean.TRUE); //aparently, FXRspecNode can't set it to null
        assertEquals(n2.getOsImageUrn(), "DUMMY");
        assertEquals(n2.getSliverTypeName(), "raw-pc");

        assertSame(n1, rspecModel.getNodeByUniqueId(n1.getUniqueId()));
        assertSame(n2, rspecModel.getNodeByUniqueId(n2.getUniqueId()));
    }

    @Test
    public void testBaseRspecModel() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);
        testBasics(testRspec);

        String rspecXmlString = testRspec.toGeni3Rspec();

        LOG.debug("Test Rspec XML: " + rspecXmlString);

        assertTrue(rspecXmlString.length() > 100);

        assertTrue(rspecXmlString.contains("type=\"request\""));
        assertTrue(rspecXmlString.contains("xsi:schemaLocation=\"http://www.geni.net/resources/rspec/3 http://www.geni.net/resources/rspec/3/request.xsd"));
        assertTrue(rspecXmlString.contains("xmlns=\"http://www.geni.net/resources/rspec/3\" "));
//        Assert.assertTrue(rspecXmlString.contains("xmlns:jFed=\"http://jfed.iminds.be/rspec/ext/jfed/1\" "));
        assertTrue(rspecXmlString.contains("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""));

        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));

        testBasics(reconstructedModel);
    }

    private static List<String> makeList(String a) {
        List<String> res = new ArrayList<String>();
        res.add(a);
        return res;
    }
    private static List<String> makeList(String a, String b) {
        List<String> res = new ArrayList<String>();
        res.add(a);
        res.add(b);
        return res;
    }

    @Test
    public void testSliverIdRspecModel() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
        assertNotNull(origN1);
        assertNotNull(origN2);
        RspecLink origL1 = testRspec.getLinkByClientId("link1");
        assertNotNull(origL1);
        assertEquals(origL1.getClientId(), "link1");

        origN1.setSliverId("urn:publicid:IDN+example.com+sliver+A");
        origN2.setSliverId("urn:publicid:IDN+example.com+sliver+B");
        origL1.setSliverId("urn:publicid:IDN+example.com+sliver+C");

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
        testBasics(reconstructedModel);

        RspecNode n1 = reconstructedModel.getNodeByClientId("firstNode");
        assertEquals(n1.getSliverId(), GeniUrn.createGeniUrnFromEncodedParts("example.com", "sliver", "A"));

        RspecNode n2 = reconstructedModel.getNodeByClientId("secondNode");
        assertEquals(n2.getSliverId(), GeniUrn.createGeniUrnFromEncodedParts("example.com", "sliver", "B"));

        RspecLink l1 = reconstructedModel.getLinkByClientId("link1");
        assertNotNull(l1.getSliverId());
        assertEquals(l1.getSliverId(), GeniUrn.createGeniUrnFromEncodedParts("example.com", "sliver", "C"));
    }

    @Test
    public void testLeaseRspecModel() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);
        Date fromA = new Date();
        Date untilA = new Date(fromA.getTime()+(5*60*1000l));
        Date fromB = new Date(fromA.getTime()+(10*60*1000l));
        Date untilB = new Date(fromA.getTime()+(15*60*1000l));
        Lease origLease1 = rspecFactory.createLease(testRspec, "leaseA", "a", fromA, untilA);
        Lease origLease2 = rspecFactory.createLease(testRspec, "leaseB", "b", fromB, untilB);

        testRspec.addLease(origLease1);
        testRspec.addLease(origLease2);

        assertEquals(testRspec.getLeases().size(), 2);


        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        assertNotNull(origN1);
        origN1.getExtraXml().add(new StringExtraXml("<ol:lease_ref xmlns:ol=\"http://nitlab.inf.uth.gr/schema/sfa/rspec/1\" id_ref=\"a\"/>"));
        origN1.getExtraXml().add(new StringExtraXml("<ol:lease_ref xmlns:ol=\"http://nitlab.inf.uth.gr/schema/sfa/rspec/1\" id_ref=\"b\"/>"));

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
        testBasics(reconstructedModel);

        assertEquals(testRspec.getLeases().size(), 2);
        Lease recLease1 = testRspec.getLeases().get(0);
        Lease recLease2 = testRspec.getLeases().get(1);
        assertEquals(recLease1.getLeaseId(), "leaseA");
        assertEquals(recLease2.getLeaseId(), "leaseB");
        assertEquals(recLease1.getClientId(), "a");
        assertEquals(recLease2.getClientId(), "b");
        assertEquals(recLease1.getValidFromDate(), fromA);
        assertEquals(recLease1.getValidUntilDate(), untilA);
        assertEquals(recLease2.getValidFromDate(), fromB);
        assertEquals(recLease2.getValidUntilDate(), untilB);
    }

    @Test
    public void testExtraXml() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
        assertNotNull(origN1);
        assertNotNull(origN2);
        RspecLink origL1 = testRspec.getLinkByClientId("link1");
        assertNotNull(origL1);
        assertEquals(origL1.getClientId(), "link1");

        origN1.getExtraXml().add(new StringExtraXml("<ens:extra xmlns:ens=\"http://example.com/something\" id=\"a\"/>"));
        origN1.getExtraXml().add(new StringExtraXml("<ens:extra xmlns:ens=\"http://example.com/something\" id=\"b\"/>"));

        origN2.getExtraXml().add(new StringExtraXml("<ens:extra xmlns:ens=\"http://example.com/something\" id=\"a\"/>"));
        origN2.getExtraXml().add(new StringExtraXml("<eens:extra xmlns:eens=\"http://example.com/something2\" id=\"a\"/>"));
        origN2.getExtraXml().add(new StringExtraXml("<ens:extraa xmlns:ens=\"http://example.com/something\" id=\"a\"/>"));

        origL1.getExtraXml().add(new StringExtraXml("<ens:extra xmlns:ens=\"http://example.com/something\" id=\"a\"/>"));
        origL1.getExtraXml().add(new StringExtraXml("<ens:extra xmlns:ens=\"http://example.com/something\" id=\"b\"/>"));

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
        testBasics(reconstructedModel);
    }

    @Test
    public void testSliverIdRspecModel2() throws Exception {
        //take a manifest
        String rspecXmlString = TestRspecsLibrary.emuManifestProb;
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));

        RspecLink l1 = reconstructedModel.getLinkByClientId("Lan");
        assertNotNull(l1.getSliverId());
        assertEquals(l1.getSliverId(), GeniUrn.createGeniUrnFromEncodedParts("emulab.net", "sliver", "199757"));
    }


    @Test
    public void testSliverTypeRspecModel() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
        RspecNode origN3 = testRspec.getNodeByClientId("thirdNode");
        origN1.setSliverType(new SliverTypeBuilder("emulab-xen").xenCores(2).xenDisk(16).build());
        origN2.setSliverType(new SliverTypeBuilder("pc").build());
        origN3.setSliverType(new SliverTypeBuilder("vm").addDiskImage("dummyImage").build());

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
//        testBasics(reconstructedModel);

        RspecNode n1 = reconstructedModel.getNodeByClientId("firstNode");
        assertEquals(n1.getSliverType(), new SliverTypeBuilder("emulab-xen").xenCores(2).xenDisk(16).build());

        RspecNode n2 = reconstructedModel.getNodeByClientId("secondNode");
        assertEquals(n2.getSliverType(), new SliverTypeBuilder("pc").build());

        RspecNode n3 = reconstructedModel.getNodeByClientId("thirdNode");
        assertEquals(n3.getSliverType(), new SliverTypeBuilder("vm").addDiskImage("dummyImage").build());
    }

    @Test
    public void testSingleSliverTypeAccessorsRspecModel() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
        RspecNode origN3 = testRspec.getNodeByClientId("thirdNode");
        origN1.setSliverType(new SliverTypeBuilder("emulab-xen").xenCores(2).xenDisk(16).build());
        origN2.setSliverType(new SliverTypeBuilder("pc").build());
        origN3.setSliverType(new SliverTypeBuilder("vm").addDiskImage("dummyImage").build());

        assertEquals(origN1.getSliverTypeName(), "emulab-xen");
        assertEquals(origN2.getSliverTypeName(), "pc");
        assertEquals(origN3.getSliverTypeName(), "vm");

        assertEquals(origN1.getSliverType(), new SliverTypeBuilder("emulab-xen").xenCores(2).xenDisk(16).build());
        assertEquals(origN2.getSliverType(), new SliverTypeBuilder("pc").build());
        assertEquals(origN3.getSliverType(), new SliverTypeBuilder("vm").addDiskImage("dummyImage").build());

        assertEquals(origN1.getSliverTypes().size(), 1);
        assertEquals(origN2.getSliverTypes().size(), 1);
        assertEquals(origN3.getSliverTypes().size(), 1);

        //test single sliver_type setters
        origN1.setSliverTypeDiskImage("dummyImage2");
        origN2.setSliverTypeName("emulab-openvz");
        origN3.setSliverType(new SliverTypeBuilder("test").addDiskImage("dummyImage3").addDiskImage(new DiskImage("diskImage4")).build());

        assertEquals(origN1.getSliverTypes().size(), 1);
        assertEquals(origN2.getSliverTypes().size(), 1);
        assertEquals(origN3.getSliverTypes().size(), 1);

        assertEquals(origN1.getSliverTypeName(), "emulab-xen");
        assertEquals(origN2.getSliverTypeName(), "emulab-openvz");
        assertEquals(origN3.getSliverTypeName(), "test");

        assertEquals(origN1.getSliverType().getDiskImages().size(), 1);
        assertEquals(origN2.getSliverType().getDiskImages().size(), 0);
        assertEquals(origN3.getSliverType().getDiskImages().size(), 2);

        assertEquals(origN1.getSliverType(), new SliverTypeBuilder("emulab-xen").addDiskImage("dummyImage2").xenCores(2).xenDisk(16).build());
        assertEquals(origN2.getSliverType(), new SliverTypeBuilder("emulab-openvz").build());
        assertEquals(origN3.getSliverType(), new SliverTypeBuilder("test").addDiskImage("dummyImage3").addDiskImage(new DiskImage("diskImage4")).build());

        origN1.setSliverTypeName("xen");
        assertEquals(origN1.getSliverType(), new SliverTypeBuilder("xen").addDiskImage("dummyImage2").xenCores(2).xenDisk(16).build());

        origN2.setSliverTypeName("pc");
        assertEquals(origN2.getSliverType(), new SliverTypeBuilder("pc").build());

        origN3.setSliverTypeName("test2");
        assertEquals(origN3.getSliverType(), new SliverTypeBuilder("test2").addDiskImage("dummyImage3").addDiskImage(new DiskImage("diskImage4")).build());

        //test single sliver_type getters
        assertEquals(origN1.getSliverTypeName(), "xen");
        assertEquals(origN2.getSliverTypeName(), "pc");
        assertEquals(origN3.getSliverTypeName(), "test2");

        assertEquals(origN1.getOsImageUrn(), "dummyImage2");
        assertEquals(origN2.getOsImageUrn(), null);
//        assertEquals(origN3.getOsImageUrn(), /*error*/);


        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
//        testBasics(reconstructedModel);

        RspecNode n1 = reconstructedModel.getNodeByClientId("firstNode");
        assertEquals(n1.getSliverType(), new SliverTypeBuilder("xen").addDiskImage("dummyImage2").xenCores(2).xenDisk(16).build());

        RspecNode n2 = reconstructedModel.getNodeByClientId("secondNode");
        assertEquals(n2.getSliverType(), new SliverTypeBuilder("pc").build());

        RspecNode n3 = reconstructedModel.getNodeByClientId("thirdNode");
        assertEquals(n3.getSliverType(), new SliverTypeBuilder("test2").addDiskImage("dummyImage3").addDiskImage(new DiskImage("diskImage4")).build());

        //test single sliver_type getters
        assertEquals(n1.getSliverTypeName(), "xen");
        assertEquals(n2.getSliverTypeName(), "pc");
        assertEquals(n3.getSliverTypeName(), "test2");

        assertEquals(n1.getOsImageUrn(), "dummyImage2");
        assertEquals(n2.getOsImageUrn(), null);
    }

    @Test
    public void testEditorPositionRspecModel() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
        origN1.setEditorX(10.0);
        origN1.setEditorY(10.0);
        origN2.setEditorX(300.0);
        origN2.setEditorY(10.0);

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
        testBasics(reconstructedModel);

        RspecNode n1 = reconstructedModel.getNodeByClientId("firstNode");
        assertEquals(n1.getEditorX(), 10.0);
        assertEquals(n1.getEditorY(), 10.0);

        RspecNode n2 = reconstructedModel.getNodeByClientId("secondNode");
        assertEquals(n2.getEditorX(), 300.0);
        assertEquals(n2.getEditorY(), 10.0);
    }

    @Test
    public void testVlanTaggingRspecModel() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
        RspecLink origLink = origN1.getLinks().get(0);
        origLink.setVlanTagging(true);
        assertTrue(origLink.hasVlanTaggingTag());
        assertTrue(origLink.isVlanTaggingEnabled());

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
        testBasics(reconstructedModel);

        RspecNode n1 = reconstructedModel.getNodeByClientId("firstNode");
        RspecNode n2 = reconstructedModel.getNodeByClientId("secondNode");
        RspecLink l = n1.getLinks().get(0);
        assertTrue(l.hasVlanTaggingTag());
        assertTrue(l.isVlanTaggingEnabled());
    }

    @Test
    public void testVlanTaggingRspecModel2() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
        RspecLink origLink = origN1.getLinks().get(0);
        origLink.setVlanTagging(false);
        assertTrue(origLink.hasVlanTaggingTag());
        assertFalse(origLink.isVlanTaggingEnabled());

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
        testBasics(reconstructedModel);

        RspecNode n1 = reconstructedModel.getNodeByClientId("firstNode");
        RspecNode n2 = reconstructedModel.getNodeByClientId("secondNode");
        RspecLink l = n1.getLinks().get(0);
        assertTrue(l.hasVlanTaggingTag());
        assertFalse(l.isVlanTaggingEnabled());
    }

    @Test
    public void testVlanTaggingRspecModel3() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
        RspecLink origLink = origN1.getLinks().get(0);
        origLink.setVlanTagging(null);
        assertFalse(origLink.hasVlanTaggingTag());
        assertFalse(origLink.isVlanTaggingEnabled());

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
        testBasics(reconstructedModel);

        RspecNode n1 = reconstructedModel.getNodeByClientId("firstNode");
        RspecNode n2 = reconstructedModel.getNodeByClientId("secondNode");
        RspecLink l = n1.getLinks().get(0);
        assertFalse(l.hasVlanTaggingTag());
        assertFalse(l.isVlanTaggingEnabled());
    }

//    @Test
//    public void testEditorNodeDescriptionTypeRspecModel() throws Exception {
//        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);
//
//        RspecNode origN1 = testRspec.getNodeByClientId("firstNode");
//        RspecNode origN2 = testRspec.getNodeByClientId("secondNode");
//        origN1.setEditorNodeDescriptionType("typeA");
//        origN2.setEditorNodeDescriptionType("typeB");
//
//        String rspecXmlString = testRspec.toGeni3Rspec();
//        LOG.debug("Test Rspec XML: " + rspecXmlString);
//        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
//        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
//        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
//        testBasics(reconstructedModel);
//
//        RspecNode n1 = reconstructedModel.getNodeByClientId("firstNode");
//        assertEquals(n1.getEditorNodeDescriptionType(), "typeA");
//
//        RspecNode n2 = reconstructedModel.getNodeByClientId("secondNode");
//        assertEquals(n2.getEditorNodeDescriptionType(), "typeB");
//    }

    @Test
    public void testSshKeysRspecModel() throws Exception {
        ModelRspec testRspec = generateBaseTestRspec(rspecFactory);

        testRspec.getSshKeys().add(new UserSpec(TEST_USER_URN1, makeList(TEST_USER_SSHKEY1, TEST_USER_SSHKEY2)));
        testRspec.getSshKeys().add(new UserSpec(TEST_USER_URN2, makeList(TEST_USER_SSHKEY3)));

        String rspecXmlString = testRspec.toGeni3Rspec();
        LOG.debug("Test Rspec XML: " + rspecXmlString);
        ModelRspec reconstructedModel = new StaxRspecParser(rspecXmlString, rspecFactory).call();
        String reconstructedRspecXmlString = reconstructedModel.toGeni3Rspec();
        assertTrue(TestRspecReconstructable.testSameXml(rspecXmlString, reconstructedRspecXmlString));
        testBasics(reconstructedModel);

        List<UserSpec> userSpecs = reconstructedModel.getSshKeys();
        assertEquals(userSpecs.size(), 2);
        UserSpec userSpec1 = userSpecs.get(0);
        UserSpec userSpec2 = userSpecs.get(1);
        assertEquals(userSpec1.getUrn(), TEST_USER_URN1);
        assertEquals(userSpec2.getUrn(), TEST_USER_URN2);
        assertEquals(userSpec1.getSshKey(), makeList(TEST_USER_SSHKEY1, TEST_USER_SSHKEY2));
        assertEquals(userSpec2.getSshKey(), makeList(TEST_USER_SSHKEY3));
    }
}
