private int getAxisPosition(XShape aAxis, double fValue, boolean bVertical) {
    int nResult = 0;

    if (aAxis != null) {
      XPropertySet aAxisProp = UnoRuntime.queryInterface(XPropertySet.class, aAxis);

      try {
        double fMin, fMax;
        fMin = ((Double) aAxisProp.getPropertyValue("Min")).doubleValue();
        fMax = ((Double) aAxisProp.getPropertyValue("Max")).doubleValue();
        double fRange = fMax - fMin;

        if (fMin <= fValue && fValue <= fMax && fRange != 0) {
          if (bVertical) {
            nResult =
                aAxis.getPosition().Y
                    + (int) ((aAxis.getSize().Height) * (1.0 - ((fValue - fMin) / fRange)));
          } else {
            nResult =
                aAxis.getPosition().X
                    + (int) ((aAxis.getSize().Width) * ((fValue - fMin) / fRange));
          }
        }
      } catch (Exception ex) {
        JOptionPane.showMessageDialog(null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE);
      }
    }
    return nResult;
  }
  // XInitialization
  public void initialize(Object[] aArguments) throws Exception, RuntimeException {
    if (aArguments.length > 0) {
      maChartDocument = UnoRuntime.queryInterface(XChartDocument.class, aArguments[0]);

      XPropertySet aDocProp = UnoRuntime.queryInterface(XPropertySet.class, maChartDocument);
      if (aDocProp != null) {
        // set base diagram which will be extended in refresh()
        aDocProp.setPropertyValue("BaseDiagram", "com.sun.star.chart.XYDiagram");
      }

      // get the draw page
      XDrawPageSupplier aPageSupp =
          UnoRuntime.queryInterface(XDrawPageSupplier.class, maChartDocument);
      if (aPageSupp != null)
        maDrawPage = UnoRuntime.queryInterface(XDrawPage.class, aPageSupp.getDrawPage());

      // get a factory for creating shapes
      maShapeFactory = UnoRuntime.queryInterface(XMultiServiceFactory.class, maChartDocument);
    }
  }
  // XRefreshable
  public void refresh() throws RuntimeException {
    // recycle shapes in first call, if document was loaded
    if (maBottomLine == null || maTopLine == null) {
      // try to recycle loaded shapes
      XPropertySet aDocProp = UnoRuntime.queryInterface(XPropertySet.class, maChartDocument);
      if (aDocProp != null) {
        try {
          XIndexAccess aShapesIA =
              UnoRuntime.queryInterface(
                  XIndexAccess.class, aDocProp.getPropertyValue("AdditionalShapes"));
          if (aShapesIA != null && aShapesIA.getCount() > 0) {
            XShape aShape;
            String aName;
            for (int i = aShapesIA.getCount() - 1; i >= 0; --i) {
              aShape = UnoRuntime.queryInterface(XShape.class, aShapesIA.getByIndex(i));
              if (aShape != null) {
                XPropertySet aProp = UnoRuntime.queryInterface(XPropertySet.class, aShape);
                aName = (String) aProp.getPropertyValue("Name");

                if (aName.equals("top")) {
                  maTopLine = aShape;
                } else if (aName.equals("bottom")) {
                  maBottomLine = aShape;
                }
              }
            }
          }
        } catch (Exception ex) {
          JOptionPane.showMessageDialog(null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE);
        }
      }
    }

    // create top line if it does not yet exist
    try {
      if (maTopLine == null) {
        maTopLine =
            UnoRuntime.queryInterface(
                XShape.class, maShapeFactory.createInstance("com.sun.star.drawing.LineShape"));
        maDrawPage.add(maTopLine);

        // make line red and thicker
        XPropertySet aShapeProp = UnoRuntime.queryInterface(XPropertySet.class, maTopLine);

        aShapeProp.setPropertyValue("LineColor", new Integer(0xe01010));
        aShapeProp.setPropertyValue("LineWidth", new Integer(50));
        aShapeProp.setPropertyValue("Name", "top");
      }
    } catch (Exception ex) {
      JOptionPane.showMessageDialog(null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE);
    }

    // create bottom line if it does not yet exist
    try {
      if (maBottomLine == null) {
        maBottomLine =
            UnoRuntime.queryInterface(
                XShape.class, maShapeFactory.createInstance("com.sun.star.drawing.LineShape"));
        maDrawPage.add(maBottomLine);

        // make line green and thicker
        XPropertySet aShapeProp = UnoRuntime.queryInterface(XPropertySet.class, maBottomLine);

        aShapeProp.setPropertyValue("LineColor", new Integer(0x10e010));
        aShapeProp.setPropertyValue("LineWidth", new Integer(50));
        aShapeProp.setPropertyValue("Name", "bottom");
      }
    } catch (Exception ex) {
      JOptionPane.showMessageDialog(null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE);
    }

    if (maTopLine == null || maBottomLine == null) {
      JOptionPane.showMessageDialog(
          null, "One of the lines is still null", "Assertion", JOptionPane.WARNING_MESSAGE);
      return;
    }

    // position lines

    // get data
    XChartDataArray aDataArray =
        UnoRuntime.queryInterface(XChartDataArray.class, maChartDocument.getData());
    double aData[][] = aDataArray.getData();

    // get axes
    XDiagram aDiagram = maChartDocument.getDiagram();
    XShape aXAxis =
        UnoRuntime.queryInterface(
            XShape.class, UnoRuntime.queryInterface(XAxisXSupplier.class, aDiagram).getXAxis());
    XShape aYAxis =
        UnoRuntime.queryInterface(
            XShape.class, UnoRuntime.queryInterface(XAxisYSupplier.class, aDiagram).getYAxis());

    // calculate points for hull
    final int nLength = aData.length;
    int i, j;
    double fMax, fMin;

    Point aMaxPtSeq[][] = new Point[1][];
    aMaxPtSeq[0] = new Point[nLength];
    Point aMinPtSeq[][] = new Point[1][];
    aMinPtSeq[0] = new Point[nLength];

    for (i = 0; i < nLength; i++) {
      fMin = fMax = aData[i][1];
      for (j = 1; j < aData[i].length; j++) {
        if (aData[i][j] > fMax) fMax = aData[i][j];
        else if (aData[i][j] < fMin) fMin = aData[i][j];
      }
      aMaxPtSeq[0][i] =
          new Point(
              getAxisPosition(aXAxis, aData[i][0], false), getAxisPosition(aYAxis, fMax, true));
      aMinPtSeq[0][i] =
          new Point(
              getAxisPosition(aXAxis, aData[i][0], false), getAxisPosition(aYAxis, fMin, true));
    }

    // apply point sequences to lines
    try {
      XPropertySet aShapeProp = UnoRuntime.queryInterface(XPropertySet.class, maTopLine);
      aShapeProp.setPropertyValue("PolyPolygon", aMaxPtSeq);

      aShapeProp = UnoRuntime.queryInterface(XPropertySet.class, maBottomLine);
      aShapeProp.setPropertyValue("PolyPolygon", aMinPtSeq);
    } catch (Exception ex) {
      JOptionPane.showMessageDialog(null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE);
    }
  }