protected ModelAnnotationGroup readModelAnnotationGroup(Node step) throws KettleXMLException {

    setModelAnnotationCategory(XMLHandler.getTagValue(step, "category"));
    setTargetOutputStep(XMLHandler.getTagValue(step, "targetOutputStep"));
    ModelAnnotationGroupXmlReader mar = new ModelAnnotationGroupXmlReader();
    ModelAnnotationGroup modelAnnotationGroup = mar.readModelAnnotationGroup(step);
    sharedDimension = modelAnnotationGroup.isSharedDimension();

    return modelAnnotationGroup;
  }
  public void saveToMetaStore(IMetaStore metaStore, ModelAnnotationGroup modelAnnotations)
      throws Exception {
    if (metaStore == null) {
      return;
    }

    ModelAnnotationManager manager = getModelAnnotationManager(modelAnnotations);
    if (modelAnnotations != null && StringUtils.isBlank(modelAnnotations.getName())) {
      modelAnnotations.setName(this.getName());
    }
    checkValidName(modelAnnotations.getName());
    manager.createGroup(modelAnnotations, metaStore);
  }
  protected ModelAnnotationManager getModelAnnotationManager(
      ModelAnnotationGroup modelAnnotationGroup) {
    if (modelAnnotationGroup.isSharedDimension()) {
      return new ModelAnnotationManager(true);
    }

    return new ModelAnnotationManager(); // default namespace
  }
  @Override
  public void readRep(
      Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases)
      throws KettleException {

    ModelAnnotationGroup modelAnnotationGroup = new ModelAnnotationGroup();
    try {

      setModelAnnotationCategory(rep.getStepAttributeString(id_step, "CATEGORY_NAME"));
      setTargetOutputStep(rep.getStepAttributeString(id_step, "TARGET_OUTPUT_STEP"));

      int nrAnnotations = rep.countNrStepAttributes(id_step, "ANNOTATION_NAME");

      // Read annotations
      for (int i = 0; i < nrAnnotations; i++) {
        String annotationName = rep.getStepAttributeString(id_step, i, "ANNOTATION_NAME");
        String annotationFieldName =
            rep.getStepAttributeString(id_step, i, "ANNOTATION_FIELD_NAME");
        String annotationType = rep.getStepAttributeString(id_step, i, "ANNOTATION_TYPE");

        // Create model annotation
        ModelAnnotation<?> modelAnnotation =
            ModelAnnotationGroupXmlReader.create(annotationType, annotationFieldName);
        if (StringUtils.isNotBlank(annotationName)) {
          modelAnnotation.setName(annotationName);
        }

        if (StringUtils.isNotBlank(annotationType)) {
          // Populate annotation properties
          Map<String, Serializable> map = new HashMap<String, Serializable>();
          for (String key : modelAnnotation.getAnnotation().getModelPropertyIds()) {
            try {
              String value = rep.getStepAttributeString(id_step, i, "PROPERTY_VALUE_" + key);
              if (StringUtils.isNotBlank(value)) {
                map.put(key, value);
              }
            } catch (KettleException ke) {
              // Ignore - not found
            }
          }
          modelAnnotation.populateAnnotation(map);
        }

        // Add to group
        modelAnnotationGroup.add(modelAnnotation);
      }

      modelAnnotationGroup.setSharedDimension(
          BooleanUtils.toBoolean(rep.getStepAttributeString(id_step, "SHARED_DIMENSION")));
      sharedDimension = modelAnnotationGroup.isSharedDimension();
      modelAnnotationGroup.setDescription(rep.getStepAttributeString(id_step, "DESCRIPTION"));

      List<DataProvider> dataProviders = new ArrayList<DataProvider>();
      int nrDataProviders = rep.countNrStepAttributes(id_step, "DP_NAME");
      for (int i = 0; i < nrDataProviders; i++) {

        DataProvider dataProvider = new DataProvider();

        dataProvider.setName(rep.getStepAttributeString(id_step, i, "DP_NAME"));
        dataProvider.setSchemaName(rep.getStepAttributeString(id_step, i, "DP_SCHEMA_NAME"));
        dataProvider.setTableName(rep.getStepAttributeString(id_step, i, "DP_TABLE_NAME"));
        dataProvider.setDatabaseMetaNameRef(
            rep.getStepAttributeString(id_step, i, "DP_DATABASE_META_NAME_REF"));

        List<ColumnMapping> columnMappings = new ArrayList<ColumnMapping>();
        long nrColumnMappings =
            rep.getStepAttributeString(id_step, "CM_COUNT_" + i) != null
                ? Long.valueOf(rep.getStepAttributeString(id_step, "CM_COUNT_" + i))
                : 0;
        for (int j = 0; j < nrColumnMappings; j++) {

          ColumnMapping columnMapping = new ColumnMapping();

          columnMapping.setName(rep.getStepAttributeString(id_step, i, "CM_NAME_" + j));
          columnMapping.setColumnName(
              rep.getStepAttributeString(id_step, i, "CM_COLUMN_NAME_" + j));
          String dataType = rep.getStepAttributeString(id_step, i, "CM_DATA_TYPE_" + j);
          if (StringUtils.isNotBlank(dataType)) {
            columnMapping.setColumnDataType(DataType.valueOf(dataType));
          }

          columnMappings.add(columnMapping);
        }

        dataProvider.setColumnMappings(columnMappings);
        dataProviders.add(dataProvider);
      }
      modelAnnotationGroup.setDataProviders(dataProviders);

    } catch (Exception e) {
      throw new KettleException(
          BaseMessages.getString(
              PKG, "ModelAnnotationMeta.Exception.UnexpectedErrorReadingStepInfoFromRepository"),
          e);
    }

    setModelAnnotations(modelAnnotationGroup);

    // This may override the loaded model annotation group
    if (StringUtils.isNotBlank(getModelAnnotationCategory())) {
      readDataFromMetaStore(metaStore);
    }
  }