@Override
  public SpecimenRequirement createSpecimenRequirement(SpecimenRequirementDetail detail) {
    SpecimenRequirement requirement = new SpecimenRequirement();
    OpenSpecimenException ose = new OpenSpecimenException(ErrorType.USER_ERROR);

    requirement.setId(detail.getId());
    requirement.setName(detail.getName());
    requirement.setLineage(Specimen.NEW);

    setCode(detail, requirement, ose);
    setLabelFormat(detail, requirement, ose);
    setLabelAutoPrintMode(detail, requirement, ose);
    setSpecimenClass(detail, requirement, ose);
    setSpecimenType(detail, requirement, ose);
    setAnatomicSite(detail, requirement, ose);
    setLaterality(detail, requirement, ose);
    setPathologyStatus(detail, requirement, ose);
    setStorageType(detail, requirement, ose);
    setInitialQty(detail, requirement, ose);
    setConcentration(detail, requirement, ose);
    setCollector(detail, requirement, ose);
    setCollectionProcedure(detail, requirement, ose);
    setCollectionContainer(detail, requirement, ose);
    setReceiver(detail, requirement, ose);
    setCpe(detail, requirement, ose);

    requirement.setSortOrder(detail.getSortOrder());
    requirement.setActivityStatus(Status.ACTIVITY_STATUS_ACTIVE.getStatus());

    ose.checkAndThrow();

    setSpecimenPoolReqs(detail, requirement, ose);
    return requirement;
  }
  @Override
  public SpecimenRequirement createDerived(DerivedSpecimenRequirement req) {
    OpenSpecimenException ose = new OpenSpecimenException(ErrorType.USER_ERROR);

    Long parentId = req.getParentSrId();
    if (parentId == null) {
      ose.addError(PARENT_REQ_REQUIRED);
      throw ose;
    }

    SpecimenRequirement parent = daoFactory.getSpecimenRequirementDao().getById(parentId);
    if (parent == null) {
      ose.addError(SrErrorCode.PARENT_NOT_FOUND);
      throw ose;
    }

    SpecimenRequirement derived = parent.copy();
    derived.setLabelFormat(null);
    derived.setLineage(Specimen.DERIVED);
    setSpecimenClass(req.getSpecimenClass(), derived, ose);
    setSpecimenType(req.getSpecimenClass(), req.getType(), derived, ose);
    setInitialQty(req.getQuantity(), derived, ose);
    setStorageType(req.getStorageType(), derived, ose);
    setConcentration(req.getConcentration(), derived, ose);
    setPathologyStatus(req.getPathology(), derived, ose);
    setLabelFormat(req.getLabelFmt(), derived, ose);
    setLabelAutoPrintMode(req.getLabelAutoPrintMode(), derived, ose);
    setCode(req.getCode(), derived, ose);
    derived.setName(req.getName());

    ose.checkAndThrow();
    derived.setParentSpecimenRequirement(parent);
    return derived;
  }
  @Override
  public List<SpecimenRequirement> createAliquots(AliquotSpecimensRequirement req) {
    OpenSpecimenException ose = new OpenSpecimenException(ErrorType.USER_ERROR);

    Long parentSrId = req.getParentSrId();
    if (parentSrId == null) {
      ose.addError(PARENT_REQ_REQUIRED);
      throw ose;
    }

    SpecimenRequirement parent = daoFactory.getSpecimenRequirementDao().getById(parentSrId);
    if (parent == null) {
      ose.addError(SrErrorCode.PARENT_NOT_FOUND);
      throw ose;
    }

    if (req.getNoOfAliquots() == null || req.getNoOfAliquots() < 1L) {
      ose.addError(SrErrorCode.INVALID_ALIQUOT_CNT);
      throw ose;
    }

    if (req.getQtyPerAliquot() == null || NumUtil.lessThanEqualsZero(req.getQtyPerAliquot())) {
      ose.addError(SrErrorCode.INVALID_QTY);
    }

    BigDecimal total = NumUtil.multiply(req.getQtyPerAliquot(), req.getNoOfAliquots());
    if (NumUtil.greaterThan(total, parent.getQtyAfterAliquotsUse())) {
      ose.addError(SrErrorCode.INSUFFICIENT_QTY);
    }

    List<SpecimenRequirement> aliquots = new ArrayList<SpecimenRequirement>();
    for (int i = 0; i < req.getNoOfAliquots(); ++i) {
      SpecimenRequirement aliquot = parent.copy();
      aliquot.setLabelFormat(null);
      aliquot.setLineage(Specimen.ALIQUOT);
      setStorageType(req.getStorageType(), aliquot, ose);
      setLabelFormat(req.getLabelFmt(), aliquot, ose);
      setLabelAutoPrintMode(req.getLabelAutoPrintMode(), aliquot, ose);
      aliquot.setInitialQuantity(req.getQtyPerAliquot());
      aliquot.setParentSpecimenRequirement(parent);
      aliquots.add(aliquot);

      ose.checkAndThrow();
    }

    return aliquots;
  }