/**
   * Test method <code>GraphElement extractStereotype() </code>.
   *
   * <p>Mainly check the size of the stereotype node.
   *
   * @throws Exception to junit.
   */
  public void testExtractStereotype() throws Exception {
    GraphEdge root = HelperUtil.createGraphEdgeInstance();

    extractor = new DefaultEdgeCompartmentExtractor(root);

    GraphNode back = (GraphNode) extractor.extractStereotype();

    Dimension d = back.getSize();

    assertTrue("The height should be 100.", d.getHeight() == 100);
    assertTrue("The width should be 1000.", d.getWidth() == 1000);
  }
  /**
   * Test method <code>void updateName(GraphElement newElement) </code>.
   *
   * <p>In this test case, the logic is simple. First creat a valid GraphNode instance. Set the
   * visible to true (the default value should be false), and expected that the extractor graph
   * element has the visible value of true.
   *
   * <p>For update, an element with visible false is created and should be updated correctly.
   *
   * <p>Also the dimension size should be updated too.
   *
   * @throws Exception to junit.
   */
  public void testUpdateName() throws Exception {
    GraphEdge root = HelperUtil.createGraphEdgeInstance();

    extractor = new DefaultEdgeCompartmentExtractor(root);

    GraphNode back = (GraphNode) extractor.extractName();
    assertTrue("The visible should be true for this GraphElement.", back.isVisible());

    GraphNode node = new GraphNode();

    SimpleSemanticModelElement semanticModel = new SimpleSemanticModelElement();
    semanticModel.setTypeinfo(EnumUtil.NAME);

    node.setSemanticModel(semanticModel);

    Dimension dimension = new Dimension();
    dimension.setHeight(new Double(10));
    dimension.setWidth(new Double(100));

    node.setSize(dimension);

    // update the Name compartment.
    extractor.updateName(node);

    back = (GraphNode) extractor.extractName();

    assertFalse("The visible should be false as it is updated.", back.isVisible());

    // check the dimension size.

    Dimension d = back.getSize();

    assertTrue("The height should be 10.", d.getHeight() == 10);
    assertTrue("The width should be 100.", d.getWidth() == 100);
  }
  /**
   * Test method <code>void updateStereotype(GraphElement newElement) </code>.
   *
   * @throws Exception to junit.
   */
  public void testUpdateStereotype() throws Exception {

    GraphEdge root = HelperUtil.createGraphEdgeInstance();

    extractor = new DefaultEdgeCompartmentExtractor(root);

    GraphNode back = (GraphNode) extractor.extractStereotype();

    Dimension d = back.getSize();

    assertTrue("The height should be 100.", d.getHeight() == 100);
    assertTrue("The width should be 1000.", d.getWidth() == 1000);

    GraphNode node = new GraphNode();

    SimpleSemanticModelElement semanticModel = new SimpleSemanticModelElement();
    semanticModel.setTypeinfo(EnumUtil.STEREOTYPE_COMPARTMENT);

    node.setSemanticModel(semanticModel);

    Dimension dimension = new Dimension();
    dimension.setHeight(new Double(10));
    dimension.setWidth(new Double(100));

    node.setSize(dimension);

    // update the stereotype node.
    extractor.updateStereotype(node);

    back = (GraphNode) extractor.extractStereotype();

    d = back.getSize();

    assertTrue("The height should be 10.", d.getHeight() == 10);
    assertTrue("The width should be 100.", d.getWidth() == 100);
  }
  /**
   * This method implements the endElement(String,String,String) method in ContentHandler interface.
   *
   * <p>This component is a plugin of XMIReader component and this method is intended to be invoked
   * by XMIReader class.
   *
   * <p>This method receives notification of the end of an element. The diagram interchange related
   * elements will be processed by this method.
   *
   * @param uri the Namespace URI;
   * @param localName The local name (without prefix), or the empty string if Namespace processing
   *     is not being performed.
   * @param qName The qualified XML 1.0 name (with prefix), or the empty string if qualified names
   *     are not available
   * @throws SAXException Any SAX exception, possibly wrapping another exception, it may be caused
   *     by reflection, etc.
   */
  public void endElement(String uri, String localName, String qName) throws SAXException {
    String elementName = ((qName != null) && (qName.trim().length() != 0)) ? qName : localName;

    int dotIndex = elementName.indexOf(".");

    // if the element represents a uml model element and its parent element is a uml element
    // property,
    // then to set the property value for the parent uml element
    if (dotIndex < 0) {
      // get the object for the current element
      Object curElementObject = getLastRefObject();

      // make the parent element name and object on the top of the stack
      // it is called before getParentHandler() method because the handler for the
      // element and the handler for parent element may be the same
      pop();

      XMIHandler handler = getParentHandler();

      if (handler != null) {
        String parentElementName = handler.getLastProperty();
        // the parent element represents a uml model property
        if (parentElementName != null && parentElementName.indexOf(".") >= 0) {

          // update the uml model element property
          // for example:
          // <UML:GraphElement.semanticModel>
          //     <UML:SimpleSemanticModelElement xmi.id = '......'/>
          // </UML:GraphElement.semanticModel>
          // The current element is "UML:SimpleSemanticModelElement", the parent element is
          // "UML:GraphElement.semanticModel".
          // Here, the semanticModel property of the corresponding GraphElement instance is set.
          setElementProperty(handler.getLastRefObject(), parentElementName, curElementObject);
        }
      }
    } else {
      // get the property name
      // for example, get "semanticModel" from "UML:GraphElement.semanticModel"
      String propName = elementName.substring(dotIndex + 1);

      // If a XMI.field element ends, validate it and add the value to XMI.field values
      if (XMI_FIELD.equals(elementName)) {
        // Only zero or two sub XMI.field elements are allowed for each XMI.field element
        int count = (Integer) getLastRefObject();
        if (count != 0 && count != 2) {
          throw new SAXException(
              "One XMI.field element has "
                  + count
                  + " child XMI.field elements, instead of 0 or 2.");
        }

        // If the current XMI.field element is an inner XMI.field element
        // for example, <XMI.field><XMI.field>0.0</XMI.field></XMI.field>
        // The first XMI.field is an outer element while the inner XMI.field element is an
        // inner element
        if (xmiFieldValue != null) {
          this.xmiFieldValues.add(xmiFieldValue);
          this.xmiFieldValue = null;
        }

      } else if (DIMENSION_ELEMENTS.contains(propName)
          || POINT_ELEMENTS.contains(propName)
          || POINTS_ELEMENTS.contains(propName)) {
        // The elements that may have XMI.field sub-elements
        if (!this.xmiFieldValues.isEmpty()) {
          // Only two XMI.field sub-elements are allowed for the point or dimension elements
          if (!POINTS_ELEMENTS.contains(propName) && this.xmiFieldValues.size() != 2) {
            throw new SAXException(
                "The "
                    + elementName
                    + " element contains "
                    + this.xmiFieldValues.size()
                    + " XMI.field elements instead of two, only two is allowed.");
          }

          try {
            if (DIMENSION_ELEMENTS.contains(propName)) {
              // process the dimension element
              // for example
              // <UML:GraphNode.size>
              //     <XMI.field>80.0776</XMI.field>
              //     <XMI.field>15.0</XMI.field>
              // </UML:GraphNode.size>
              Dimension dimension = new Dimension();
              dimension.setWidth(Double.valueOf(this.xmiFieldValues.get(0).toString()));
              dimension.setHeight(Double.valueOf(this.xmiFieldValues.get(1).toString()));

              this.setElementProperty(getLastRefObject(), elementName, dimension);
            } else if (POINT_ELEMENTS.contains(propName)) {
              // process the point element
              // <UML:GraphElement.position>
              //     <XMI.field>2.0</XMI.field>
              //     <XMI.field>2.0</XMI.field>
              // </UML:GraphElement.position>
              Point point = new Point();
              point.setX(Double.valueOf(this.xmiFieldValues.get(0).toString()));
              point.setY(Double.valueOf(this.xmiFieldValues.get(1).toString()));

              this.setElementProperty(getLastRefObject(), elementName, point);
            } else {
              // process the point collect element
              // <UML:GraphEdge.waypoints>
              //   <XMI.field>
              //     <XMI.field>110.0</XMI.field>
              //     <XMI.field>205.0</XMI.field>
              //   </XMI.field>
              //   <XMI.field>
              //     <XMI.field>0.0</XMI.field>
              //     <XMI.field>0.0</XMI.field>
              //   </XMI.field>
              //   ......
              // </UML:GraphEdge.waypoints>
              int len = this.xmiFieldValues.size();

              // Add all the points
              for (int i = 0; i < len / 2; i++) {
                Point point = new Point();
                point.setX(Double.valueOf(this.xmiFieldValues.get(2 * i).toString()));
                point.setY(Double.valueOf(this.xmiFieldValues.get(2 * i + 1).toString()));

                this.setElementProperty(getLastRefObject(), elementName, point);
              }
            }
          } catch (NumberFormatException e) {
            throw new SAXException(
                "NumberFormatException occurs while converting string to double value.", e);
          }
        }
      }

      // make the parent element name and object because on the top of the stack
      // the name and object for the current element will be discarded
      pop();
    }
  }