protected double generateClassValue(Instances data) throws Exception {
    double result = Double.NaN;
    
    switch (m_ClassType) {
      case Attribute.NUMERIC:
        result = m_Random.nextFloat() * 0.25
            + Math.abs(m_Random.nextInt())
            % Math.max(2, m_NumNominal);
        break;
        
      case Attribute.NOMINAL:
        result = Math.abs(m_Random.nextInt()) % data.numClasses();
        break;
        
      case Attribute.STRING:
        String str = "";
        for (int n = 0; n < m_Words.length; n++) {
          if ( (n > 0) && (m_WordSeparators.length() != 0) )
            str += m_WordSeparators.charAt(m_Random.nextInt(m_WordSeparators.length()));
          str += m_Words[m_Random.nextInt(m_Words.length)];
        }
        result = data.classAttribute().addStringValue(str);
        break;
        
      case Attribute.DATE:
        result = data.classAttribute().parseDate(
                (2000 + m_Random.nextInt(100)) + "-01-01");
        break;
        
      case Attribute.RELATIONAL:
        if (getRelationalClassFormat() != null) {
          result = data.classAttribute().addRelation(getRelationalClassFormat());
        }
        else {
          TestInstances dataset = new TestInstances();
          dataset.setNumNominal(getNumRelationalNominal());
          dataset.setNumNominalValues(getNumRelationalNominalValues());
          dataset.setNumNumeric(getNumRelationalNumeric());
          dataset.setNumString(getNumRelationalString());
          dataset.setNumDate(getNumRelationalDate());
          dataset.setNumInstances(getNumInstancesRelational());
          dataset.setClassType(Attribute.NOMINAL);  // dummy to avoid endless recursion, will be deleted anyway
          Instances rel = new Instances(dataset.generate());
          int clsIndex = rel.classIndex();
          rel.setClassIndex(-1);
          rel.deleteAttributeAt(clsIndex);
          result = data.classAttribute().addRelation(rel);
        }
        break;
    }
    
    return result;
  }