All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hyperledger.composer.bna.model.Model Maven / Gradle / Ivy

The newest version!
/*
 * Copyright IBM Corp. 2017 All Rights Reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

package org.hyperledger.composer.bna.model;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.hyperledger.composer.annotation.Asset;
import org.hyperledger.composer.annotation.Concept;
import org.hyperledger.composer.annotation.Participant;
import org.hyperledger.composer.annotation.Transaction;
import org.hyperledger.composer.bna.part.CtoPart;

public class Model {

  public static final List> MODEL_ANNOTATIONS
      = Arrays.asList(Asset.class, Participant.class, Transaction.class, Concept.class);
  private final List fields;
  private final CtoPart ctoPart;
  String name;
  Model.ModelType type;
  private String namespace;
  private FieldModel primaryKey;
  private String parentName;

  /**
   * constructor.
   *
   * @param ctoPart the {@code CtoPart}
   */
  public Model(CtoPart ctoPart) {
    this.ctoPart = ctoPart;
    this.ctoPart.addEntry(this);
    this.fields = new LinkedList<>();
  }

  static boolean isPointerType(Field field) {
    for (Class annotation : MODEL_ANNOTATIONS) {
      if (checkFieldAnnotation(field, annotation)) {
        return true;
      }
    }
    return false;
  }

  static boolean checkFieldAnnotation(Field field, Class annotation) {
    Class type = field.getType();
    type = type.isArray() ? type.getComponentType() : type;
    return type.isAnnotationPresent(annotation);
  }

  public Model name(String name) {
    this.name = name;
    return this;
  }

  public Model namespace(String namespace) {
    this.namespace = namespace;
    return this;
  }

  public Model type(Class type) {
    this.type = ModelType.valueOf(type.getSimpleName().toUpperCase());
    return this;
  }

  /**
   * set the parent for this {@code Model}.
   *
   * @param parentNamespace namespace of the parent
   * @param parentName name of the parent
   * @return this {@code Model}
   */
  public Model parent(String parentNamespace, String parentName) {
    this.parentName = parentName;
    this.addDependency(parentNamespace, parentNamespace + '.' + parentName);
    return this;
  }

  /**
   * add a {@code FieldModel} for this {@code Model}.
   *
   * @param field the {@code FieldModel}
   * @param isPrimary true if the {@code FieldModel} is the primary key
   * @return this {@code Model}
   */
  public Model addField(FieldModel field, boolean isPrimary) {
    if (type == ModelType.TRANSACTION) {
      String transactionName = namespace + "." + name;
      if (isPrimary) {
        throw new IllegalArgumentException(
            "No primary key for transaction type:" + transactionName);
      }
      if ("transactionId".equals(field.name())) {
        throw new IllegalArgumentException(
            "No field named 'transactionId' for transaction type:" + transactionName);
      }
    }
    if (isPrimary && primaryKey != null) {
      throw new IllegalArgumentException(
          String.format("Duplicate primary key: %s, %s", primaryKey.name(), field.name()));
    }
    this.fields.add(field);
    this.addDependency(field.namespace(), field.dependency());
    if (isPrimary) {
      this.primaryKey = field;
    }
    return this;
  }

  private void addDependency(String namespace, String dependency) {
    if (dependency != null && !this.namespace.equals(namespace)) {
      this.ctoPart.addEntry(dependency);
    }
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append(type.toString().toLowerCase());
    builder.append(' ');
    builder.append(name);
    switch (type) {
      case TRANSACTION:
      case CONCEPT:
        if (parentName != null) {
          builder.append(" extends ");
          builder.append(parentName);
        }
        break;
      default:
        if (primaryKey == null) {
          if (parentName == null) {
            throw new IllegalArgumentException(
                "primary key of String type must be given for " + this.namespace + "." + this.name);
          }
          builder.append(" extends ");
          builder.append(parentName);
        } else {
          builder.append(" identified by ");
          builder.append(primaryKey.name());
        }
    }
    builder.append(" {\n");
    for (FieldModel field : fields) {
      builder.append(field.toString()).append('\n');
    }
    builder.append("}\n");
    return builder.toString();
  }

  public enum ModelType {
    ASSET, PARTICIPANT, CONCEPT, TRANSACTION, ENUM
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy