/** tests the canvas. This one as XmlElementRefs, XmlElements, and an attachment... */
  public void testCanvas() throws Exception {
    Canvas canvas = new Canvas();
    Bus bus = new Bus();
    bus.setId("busId");
    Rectangle busFrame = new Rectangle();
    busFrame.setWidth(100);
    bus.setFrame(busFrame);
    Cat cat = new Cat();
    cat.setId("catId");
    Circle catFace = new Circle();
    catFace.setRadius(30);
    cat.setFace(catFace);
    House house = new House();
    house.setId("houseId");
    Rectangle houseBase = new Rectangle();
    houseBase.setWidth(76);
    house.setBase(houseBase);
    canvas.setFigures(Arrays.asList(bus, cat, house));
    Rectangle rectangle = new Rectangle();
    rectangle.setHeight(50);
    rectangle.setId("rectId");
    Circle circle = new Circle();
    circle.setRadius(10);
    circle.setId("circleId");
    Triangle triangle = new Triangle();
    triangle.setBase(80);
    triangle.setId("triId");
    canvas.setShapes(Arrays.asList(rectangle, circle, triangle));
    byte[] swaRefBytes =
        "This is a bunch of random bytes that are to be used as an SWA ref attachment.".getBytes();
    byte[] explicitBase64Bytes =
        "This is some more random bytes that are to be used as a base 64 encoded attachment."
            .getBytes();
    byte[] attachment1Bytes =
        "This is some more random bytes that are to be used as the first MTOM attachment."
            .getBytes();
    byte[] attachment2Bytes =
        "This is some more random bytes that are to be used as the second MTOM attachment."
            .getBytes();
    byte[] attachment3Bytes =
        "This is some more random bytes that are to be used as the third MTOM attachment."
            .getBytes();
    CanvasAttachment attachment1 = new CanvasAttachment();
    attachment1.setValue(attachment1Bytes);
    CanvasAttachment attachment2 = new CanvasAttachment();
    attachment2.setValue(attachment2Bytes);
    CanvasAttachment attachment3 = new CanvasAttachment();
    attachment3.setValue(attachment3Bytes);
    ByteArrayDataSource dataSource =
        new ByteArrayDataSource(swaRefBytes, "application/octet-stream");
    dataSource.setName("somename");
    // todo: uncomment when JAXB bug is fixed
    //    canvas.setBackgroundImage(new DataHandler(dataSource));
    canvas.setExplicitBase64Attachment(explicitBase64Bytes);
    canvas.setOtherAttachments(Arrays.asList(attachment1, attachment2, attachment3));

    JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
    ObjectMapper canvasMapper =
        provider.locateMapper(Canvas.class, MediaType.APPLICATION_JSON_TYPE);
    ObjectMapper clientMapper = new ObjectMapper();
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    canvasMapper.writeValue(out, canvas);
    // set up the attachments that were written

    shapes.json.draw.Canvas clientCanvas =
        clientMapper.readValue(
            new ByteArrayInputStream(out.toByteArray()), shapes.json.draw.Canvas.class);
    Collection<ObjectNode> clientShapes = clientCanvas.getShapes();
    assertEquals(3, clientShapes.size());
    for (ObjectNode shape : clientShapes) {
      assertEquals(1, shape.size());
      String shapeKey = shape.getFields().next().getKey();
      shape = (ObjectNode) shape.get(shapeKey);
      if ("circle".equals(shapeKey)) {
        assertEquals("circleId", shape.get("id").getTextValue());
        assertEquals(10, shape.get("radius").getIntValue());
      } else if ("triangle".equals(shapeKey)) {
        assertEquals("triId", shape.get("id").getTextValue());
        assertEquals(80, shape.get("base").getIntValue());
      } else if ("rectangle".equals(shapeKey)) {
        assertEquals("rectId", shape.get("id").getTextValue());
        assertEquals(50, shape.get("height").getIntValue());
      } else {
        fail("Unknown shape: " + shapeKey);
      }
    }

    Collection<ObjectNode> clientFigures = clientCanvas.getFigures();
    assertEquals(3, clientFigures.size());
    for (ObjectNode figure : clientFigures) {
      assertEquals(1, figure.size());
      String figureKey = figure.getFields().next().getKey();
      figure = (ObjectNode) figure.get(figureKey);
      if ("bus".equals(figureKey)) {
        assertEquals("busId", figure.get("id").getTextValue());
        assertTrue(figure.get("frame") != null);
        assertEquals(100, figure.get("frame").get("width").getIntValue());
      } else if ("cat".equals(figureKey)) {
        assertEquals("catId", figure.get("id").getTextValue());
        assertTrue(figure.get("circle") != null);
        assertEquals(30, figure.get("circle").get("radius").getIntValue());
      } else if ("house".equals(figureKey)) {
        assertEquals("houseId", figure.get("id").getTextValue());
        assertTrue(figure.get("base") != null);
        assertEquals(76, figure.get("base").get("width").getIntValue());
      } else {
        fail("Unknown figure: " + figure);
      }
    }

    //    DataHandler backgroundImage = clientCanvas.getBackgroundImage();
    //    InputStream attachmentStream = backgroundImage.getInputStream();
    //    ByteArrayOutputStream bgImageIn = new ByteArrayOutputStream();
    //    int byteIn = attachmentStream.read();
    //    while (byteIn > 0) {
    //      bgImageIn.write(byteIn);
    //      byteIn = attachmentStream.read();
    //    }
    //    assertTrue(Arrays.equals(swaRefBytes, bgImageIn.toByteArray()));

    byte[] base64Attachment = clientCanvas.getExplicitBase64Attachment();
    assertNotNull(base64Attachment);
    assertTrue(Arrays.equals(explicitBase64Bytes, base64Attachment));

    Collection otherAttachments = clientCanvas.getOtherAttachments();
    assertEquals(3, otherAttachments.size());
    Iterator attachmentsIt = otherAttachments.iterator();
    int attachmentCount = 0;
    while (attachmentsIt.hasNext()) {
      shapes.json.draw.CanvasAttachment otherAttachment =
          (shapes.json.draw.CanvasAttachment) attachmentsIt.next();
      byte[] otherAttachmentBytes = otherAttachment.getValue();
      if (Arrays.equals(attachment1Bytes, otherAttachmentBytes)) {
        attachmentCount++;
      } else if (Arrays.equals(attachment2Bytes, otherAttachmentBytes)) {
        attachmentCount++;
      } else if (Arrays.equals(attachment3Bytes, otherAttachmentBytes)) {
        attachmentCount++;
      } else {
        fail("Unknown attachment.");
      }
    }
    assertEquals(3, attachmentCount);

    clientCanvas.setShapes(null); // @XmlElementRefs can't be (de)serialized.
    out = new ByteArrayOutputStream();
    clientMapper.writeValue(out, clientCanvas);
    canvas = canvasMapper.readValue(new ByteArrayInputStream(out.toByteArray()), Canvas.class);

    Collection shapes = canvas.getShapes();
    assertNull(shapes);
    //    assertEquals(3, shapes.size());
    //    for (Object Shape : shapes) {
    //      if (Shape instanceof Circle) {
    //        assertEquals("circleId", ((Circle) Shape).getId());
    //        assertEquals(10, ((Circle) Shape).getRadius());
    //      }
    //      else if (Shape instanceof Rectangle) {
    //        assertEquals("rectId", ((Rectangle) Shape).getId());
    //        assertEquals(50, ((Rectangle) Shape).getHeight());
    //      }
    //      else if (Shape instanceof Triangle) {
    //        assertEquals("triId", ((Triangle) Shape).getId());
    //        assertEquals(80, ((Triangle) Shape).getBase());
    //      }
    //      else {
    //        fail("Unknown shape: " + Shape);
    //      }
    //    }

    Collection figures = canvas.getFigures();
    assertEquals(3, figures.size());
    for (Object Figure : figures) {
      if (Figure instanceof Bus) {
        bus = (Bus) Figure;
        assertEquals("busId", bus.getId());
        Rectangle BusFrame = bus.getFrame();
        assertNotNull(BusFrame);
        assertEquals(100, busFrame.getWidth());
      } else if (Figure instanceof Cat) {
        cat = (Cat) Figure;
        assertEquals("catId", cat.getId());
        Circle CatFace = cat.getFace();
        assertNotNull(CatFace);
        assertEquals(30, CatFace.getRadius());
      } else if (Figure instanceof House) {
        house = (House) Figure;
        assertEquals("houseId", house.getId());
        Rectangle HouseBase = house.getBase();
        assertNotNull(HouseBase);
        assertEquals(76, HouseBase.getWidth());
      } else {
        fail("Unknown figure: " + Figure);
      }
    }

    //    backgroundImage = canvas.getBackgroundImage();
    //    attachmentStream = backgroundImage.getInputStream();
    //    bgImageIn = new ByteArrayOutputStream();
    //    byteIn = attachmentStream.read();
    //    while (byteIn > 0) {
    //      bgImageIn.write(byteIn);
    //      byteIn = attachmentStream.read();
    //    }
    //
    //    assertTrue(Arrays.equals(swaRefBytes, bgImageIn.toByteArray()));

    base64Attachment = canvas.getExplicitBase64Attachment();
    assertNotNull(base64Attachment);
    assertTrue(Arrays.equals(explicitBase64Bytes, base64Attachment));

    otherAttachments = canvas.getOtherAttachments();
    assertEquals(3, otherAttachments.size());
    attachmentsIt = otherAttachments.iterator();
    attachmentCount = 0;
    while (attachmentsIt.hasNext()) {
      CanvasAttachment otherAttachment = (CanvasAttachment) attachmentsIt.next();
      byte[] otherAttachmentBytes = otherAttachment.getValue();
      if (Arrays.equals(attachment1Bytes, otherAttachmentBytes)) {
        attachmentCount++;
      } else if (Arrays.equals(attachment2Bytes, otherAttachmentBytes)) {
        attachmentCount++;
      } else if (Arrays.equals(attachment3Bytes, otherAttachmentBytes)) {
        attachmentCount++;
      } else {
        fail("Unknown attachment.");
      }
    }
    assertEquals(3, attachmentCount);

    // todo: test element ref to an attachment element
    // todo: test element refs of attachment elements.
  }
  /** tests cat. This one has IDREFs. */
  public void testCat() throws Exception {
    Cat cat = new Cat();
    Circle face = new Circle();
    face.setRadius(20);
    cat.setFace(face);
    Triangle ear = new Triangle();
    ear.setBase(5);
    ear.setHeight(10);
    ear.setId("earId");
    cat.setEars(Arrays.asList(ear, ear));

    // The eyes are the same as the ears, but so it needs to be for this test.
    cat.setEyes(new Triangle[] {ear, ear});

    Line noseLine = new Line();
    noseLine.setId("noseId");
    Line mouthLine = new Line();
    mouthLine.setId("mouthLine");

    cat.setNose(noseLine);
    cat.setMouth(mouthLine);
    cat.setWhiskers(Arrays.asList(noseLine, mouthLine));

    JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
    ObjectMapper catMapper = provider.locateMapper(Cat.class, MediaType.APPLICATION_JSON_TYPE);
    ObjectMapper clientMapper = new ObjectMapper();
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    catMapper.writeValue(out, cat);
    shapes.json.animals.Cat clientCat =
        clientMapper.readValue(
            new ByteArrayInputStream(out.toByteArray()), shapes.json.animals.Cat.class);

    shapes.json.Circle clientFace = clientCat.getFace();
    assertEquals(20, clientFace.getRadius());
    assertEquals(2, clientCat.getEars().size());
    shapes.json.Triangle[] clientEars =
        (shapes.json.Triangle[]) clientCat.getEars().toArray(new shapes.json.Triangle[2]);
    assertNotSame(
        "referential integrity should NOT have been preserved since Jackson doesn't support it yet",
        clientEars[0],
        clientEars[1]);
    assertEquals(5, clientEars[0].getBase());
    assertEquals(10, clientEars[0].getHeight());
    assertEquals("earId", clientEars[0].getId());
    assertEquals(5, clientEars[1].getBase());
    assertEquals(10, clientEars[1].getHeight());
    assertEquals("earId", clientEars[1].getId());

    shapes.json.Triangle[] clientEyes = clientCat.getEyes();
    assertEquals(2, clientEyes.length);
    assertNotSame(clientEyes[0], clientEyes[1]);
    assertEquals(5, clientEyes[0].getBase());
    assertEquals(10, clientEyes[0].getHeight());
    assertEquals("earId", clientEyes[0].getId());
    assertEquals(5, clientEyes[1].getBase());
    assertEquals(10, clientEyes[1].getHeight());
    assertEquals("earId", clientEyes[1].getId());
    assertFalse(
        "The ears should NOT be the same object as one of the eyes since Jackson doesn't support referential integrity.",
        clientEars[0] == clientEyes[0] || clientEars[0] == clientEyes[1]);

    shapes.json.Line clientNose = clientCat.getNose();
    assertEquals("noseId", clientNose.getId());
    shapes.json.Line clientMouth = clientCat.getMouth();
    assertEquals("mouthLine", clientMouth.getId());
    assertFalse(
        "The nose line should NOT also be one of the whiskers since Jackson doesn't support referential integrity.",
        clientCat.getWhiskers().contains(clientNose));
    assertFalse(
        "The mouth line should NOT also be one of the whiskers since Jackson doesn't support referential integrity.",
        clientCat.getWhiskers().contains(clientMouth));

    out = new ByteArrayOutputStream();
    clientMapper.writeValue(out, clientCat);
    cat = catMapper.readValue(new ByteArrayInputStream(out.toByteArray()), Cat.class);

    face = cat.getFace();
    assertEquals(20, face.getRadius());
    assertEquals(2, cat.getEars().size());
    Triangle[] ears = cat.getEars().toArray(new Triangle[2]);
    assertNotSame(
        "referential integrity should NOT have been preserved since Jackson doesn't support referential integrity.",
        ears[0],
        ears[1]);
    assertEquals(5, ears[0].getBase());
    assertEquals(10, ears[0].getHeight());
    assertEquals("earId", ears[0].getId());

    Triangle[] eyes = cat.getEyes();
    assertEquals(2, eyes.length);
    assertNotSame(eyes[0], eyes[1]);
    assertEquals(5, eyes[0].getBase());
    assertEquals(10, eyes[0].getHeight());
    assertEquals("earId", eyes[0].getId());
    assertEquals(5, eyes[1].getBase());
    assertEquals(10, eyes[1].getHeight());
    assertEquals("earId", eyes[1].getId());
    assertFalse(
        "The ears should NOT be the same object as one of the eyes since Jackson doesn't support referential integrity.",
        ears[0] == eyes[0] || ears[0] == eyes[1]);

    Line nose = cat.getNose();
    assertEquals("noseId", nose.getId());
    Line mouth = cat.getMouth();
    assertEquals("mouthLine", mouth.getId());
    assertFalse(
        "The nose line should also be one of the whiskers since Jackson doesn't support referential integrity.",
        cat.getWhiskers().contains(nose));
    assertFalse(
        "The mouth line should also be one of the whiskers since Jackson doesn't support referential integrity.",
        cat.getWhiskers().contains(mouth));
  }