/*
  * (non-Javadoc)
  *
  * @see org.geppetto.core.model.state.visitors.DefaultStateVisitor#visitSimpleStateNode(org.geppetto.core.model.state.SimpleStateNode)
  */
 @Override
 public boolean visitVariableNode(VariableNode node) {
   String variable = node.getInstancePath();
   H5File file = _recording.getHDF5();
   String variablePath = "/" + variable.replace(".", "/");
   Dataset v = (Dataset) FileFormat.findObject(file, variablePath);
   if (v != null) {
     Object dataRead;
     try {
       dataRead = v.read();
       Quantity quantity = new Quantity();
       AValue readValue = null;
       if (dataRead instanceof double[]) {
         double[] dr = (double[]) dataRead;
         readValue = ValuesFactory.getDoubleValue(dr[_currentIndex]);
       } else if (dataRead instanceof float[]) {
         float[] fr = (float[]) dataRead;
         readValue = ValuesFactory.getFloatValue(fr[_currentIndex]);
       } else if (dataRead instanceof int[]) {
         int[] ir = (int[]) dataRead;
         readValue = ValuesFactory.getIntValue(ir[_currentIndex]);
       }
       quantity.setValue(readValue);
       node.addQuantity(quantity);
     } catch (ArrayIndexOutOfBoundsException e) {
       _endOfSteps = e.getMessage();
     } catch (Exception | OutOfMemoryError e) {
       _errorMessage = e.getMessage();
     }
   }
   return super.visitVariableNode(node);
 }
  /*
   * (non-Javadoc)
   *
   * @see org.geppetto.core.model.state.visitors.DefaultStateVisitor#visitSimpleStateNode(org.geppetto.core.model.state.SimpleStateNode)
   */
  @Override
  public boolean visitSkeletonAnimationNode(SkeletonAnimationNode node) {
    String variable = node.getInstancePath();
    H5File file = _recording.getHDF5();
    String variablePath = "/" + variable.replace(".", "/");
    Dataset v = (Dataset) FileFormat.findObject(file, variablePath);
    if (v != null) {
      Object dataRead;
      try {
        dataRead = v.read();

        // get metadata from recording node
        List<Attribute> attributes = v.getMetadata();
        String meta = "";

        for (Attribute a : attributes) {
          if (a.getName().equals("custom_metadata")) meta = ((String[]) a.getValue())[0];
        }

        // split into key value pair
        Map<String, String> metaMap = StringSplitter.keyValueSplit(meta, ";");

        double[] flatMatrices = null;
        if (dataRead instanceof double[]) {
          double[] dr = (double[]) dataRead;

          // get items of interest based on matrix dimension and items per step
          int itemsPerStep = Integer.parseInt(metaMap.get("items_per_step"));
          int startIndex = _currentIndex * itemsPerStep;
          int endIndex = startIndex + (itemsPerStep);

          if (endIndex <= dr.length) {
            flatMatrices = Arrays.copyOfRange(dr, startIndex, endIndex);
          } else {
            throw new ArrayIndexOutOfBoundsException("ArrayIndexOutOfBounds");
          }
        }

        // set matrices on skeleton animation node
        node.addSkeletonTransformation(Arrays.asList(ArrayUtils.toObject(flatMatrices)));
      } catch (ArrayIndexOutOfBoundsException e) {
        _endOfSteps = e.getMessage();
      } catch (Exception | OutOfMemoryError e) {
        _errorMessage = e.getMessage();
      }
    }

    return super.visitSkeletonAnimationNode(node);
  }