/**
   * Determines a platform type the application is running on.
   *
   * @return current platform type
   */
  public static PlatformType getPlatform() {
    if (activePlatformType != null) return activePlatformType;
    activePlatformType = PlatformType.DEFAULT;
    PrivilegedAction<String> doGetOSName =
        new PrivilegedAction<String>() {

          @Override
          public String run() {
            return System.getProperty("os.name");
          }
        };

    String osName = AccessController.doPrivileged(doGetOSName);
    if (osName != null) {
      osName = osName.toLowerCase();
      for (PlatformType platformType : PlatformType.values()) {
        for (String pattern : platformType.getPatterns()) {
          if (osName.startsWith(pattern)) {
            return activePlatformType = platformType;
          }
        }
      }
    }
    return activePlatformType = PlatformType.DEFAULT;
  }
  /**
   * Use this in place of valueOf.
   *
   * @param value real value
   * @return PlatformType corresponding to the value
   */
  public static PlatformType fromValue(String value) {
    if (value == null || "".equals(value)) {
      throw new IllegalArgumentException("Value cannot be null or empty!");
    }

    for (PlatformType enumEntry : PlatformType.values()) {
      if (enumEntry.toString().equals(value)) {
        return enumEntry;
      }
    }

    throw new IllegalArgumentException("Cannot create enum from " + value + " value!");
  }
  /**
   * Builds the SRA {@link PlatformType}, this is partly taken from the ISATAB "sequencing" protocol
   * and partly from the "platform" field in the ISATAB assay section (investigation file).
   *
   * <p>Some of these parameters are mandatory in SRA, and/or constrained to certain values, so the
   * method raises an exception in case they're not defined. TODO: this could be replaced by relying
   * on the ISA Parameter Value[sequencing instrument] available from latest configuration
   */
  protected PlatformType buildExportedPlatform(final Assay assay) {
    ProtocolApplication pApp = getProtocol(assay, "sequencing");
    if (pApp == null) {
      return null;
    }
    Protocol proto = pApp.getProtocol();

    // Get the instrument information associated to that sequencing protocol
    // TODO: PRS: rely on a ISA Parameter Value[sequencing instrument] instead to obtain the
    // information
    // TODO: PRS: check against the declared ISA assay platform

    String sequencinginst = getParameterValue(assay, pApp, "sequencing instrument", true);

    PlatformType.LS454.INSTRUMENTMODEL.Enum.forString(sequencinginst);

    if (("454 GS".equalsIgnoreCase(sequencinginst)
        || "454 GS 20".equalsIgnoreCase(sequencinginst)
        || "454 GS FLX".equalsIgnoreCase(sequencinginst)
        || "454 GS FLX Titanium".equalsIgnoreCase(sequencinginst)
        || "454 GS Junior".equalsIgnoreCase(sequencinginst)
        || "GS20".equalsIgnoreCase(sequencinginst)
        || "GS FLX".equalsIgnoreCase(sequencinginst))) {

      // todo finish
    }

    String xinstrument = null;

    for (ProtocolComponent pcomp : proto.getComponents()) {
      for (OntologyTerm ctype : pcomp.getOntologyTerms()) {
        String pctypeStr = ctype.getName().toLowerCase();
        if (pctypeStr.contains("instrument") || pctypeStr.contains("sequencer")) {
          xinstrument = pcomp.getValue();
          break;
        }
      }
    }

    if (xinstrument == null) {
      String msg =
          MessageFormat.format(
              "The assay file of type {0} / {1} for study {2} has no Instrument declared in the ISA Sequencing Protocol",
              assay.getMeasurement().getName(),
              assay.getTechnologyName(),
              assay.getStudy().getAcc());
      throw new TabMissingValueException(msg);
    }

    PlatformType xplatform = PlatformType.Factory.newInstance();
    String platform = StringUtils.upperCase(assay.getAssayPlatform());

    if (platform.toLowerCase().contains("454")) {

      // if ("LS454".equalsIgnoreCase(platform)) {

      PlatformType.LS454 ls454 = PlatformType.LS454.Factory.newInstance();
      ls454.setINSTRUMENTMODEL(PlatformType.LS454.INSTRUMENTMODEL.Enum.forString(xinstrument));
      ls454.setKEYSEQUENCE(getParameterValue(assay, pApp, "Key Sequence", false));
      ls454.setFLOWSEQUENCE(getParameterValue(assay, pApp, "Flow Sequence", false));

      String flowCountStr = getParameterValue(assay, pApp, "Flow Count", false);
      ls454.setFLOWCOUNT(new BigInteger(checkNumericParameter(flowCountStr)));
      xplatform.setLS454(ls454);

    } else if (platform.toLowerCase().contains("illumina")) {
      PlatformType.ILLUMINA illumina = PlatformType.ILLUMINA.Factory.newInstance();
      illumina.setINSTRUMENTMODEL(
          PlatformType.ILLUMINA.INSTRUMENTMODEL.Enum.forString(xinstrument));
      illumina.setCYCLESEQUENCE(getParameterValue(assay, pApp, "Cycle Sequence", true));
      illumina.setCYCLECOUNT(
          new BigInteger(
              checkNumericParameter(getParameterValue(assay, pApp, "Cycle Count", true))));
      xplatform.setILLUMINA(illumina);

    } else if (platform.toLowerCase().contains("helicos")) {
      // ("HELICOS".equalsIgnoreCase(platform)) {
      PlatformType.HELICOS helicos = PlatformType.HELICOS.Factory.newInstance();
      helicos.setINSTRUMENTMODEL(PlatformType.HELICOS.INSTRUMENTMODEL.Enum.forString(xinstrument));
      helicos.setFLOWSEQUENCE(getParameterValue(assay, pApp, "Flow Sequence", true));
      helicos.setFLOWCOUNT(
          new BigInteger(
              checkNumericParameter(getParameterValue(assay, pApp, "Flow Count", true))));
      xplatform.setHELICOS(helicos);

    } else if (platform.toLowerCase().contains("solid")) {
      // ("ABI SOLID".equalsIgnoreCase(platform) || "ABI_SOLID".equalsIgnoreCase(platform)) {
      PlatformType.ABISOLID abisolid = PlatformType.ABISOLID.Factory.newInstance();
      abisolid.setINSTRUMENTMODEL(
          PlatformType.ABISOLID.INSTRUMENTMODEL.Enum.forString(xinstrument));

      {
        String colorMatrix = getParameterValue(assay, pApp, "Color Matrix", false);
        // single dibase colours are semicolon-separated
        if (colorMatrix != null) {

          PlatformType.ABISOLID.COLORMATRIX xcolorMatrix =
              PlatformType.ABISOLID.COLORMATRIX.Factory.newInstance();

          String dibases[] = colorMatrix.split("\\;");
          if (dibases != null && dibases.length > 0) {

            PlatformType.ABISOLID.COLORMATRIX.COLOR xcolors[] =
                new PlatformType.ABISOLID.COLORMATRIX.COLOR[dibases.length];
            int i = 0;
            for (String dibase : dibases) {
              PlatformType.ABISOLID.COLORMATRIX.COLOR xcolor =
                  PlatformType.ABISOLID.COLORMATRIX.COLOR.Factory.newInstance();
              xcolor.setDibase(dibase);
              xcolors[i++] = xcolor;
            }
            xcolorMatrix.setCOLORArray(xcolors);
            abisolid.setCOLORMATRIX(xcolorMatrix);
          }
        }
      }

      {
        String colorMatrixCode = getParameterValue(assay, pApp, "Color Matrix Code", false);
        if (colorMatrixCode != null) {
          abisolid.setCOLORMATRIXCODE(colorMatrixCode);
        }
      }

      // TODO: remove, deprecated abisolid.setCYCLECOUNT ( new BigInteger ( getParameterValue (
      // assay, papp, "Cycle Count", true ) ) );

      abisolid.setSEQUENCELENGTH(
          new BigInteger(
              checkNumericParameter(getParameterValue(assay, pApp, "Cycle Count", false))));

      xplatform.setABISOLID(abisolid);
    } else {
      throw new TabInvalidValueException(
          MessageFormat.format(
              "The SRA platform ''{0}'' for the assay ''{1}''/''{2}'' in the study ''{3}'' is invalid. Please supply the Platform information for the Assay in the Investigation file",
              platform,
              assay.getMeasurement().getName(),
              assay.getTechnologyName(),
              assay.getStudy().getAcc()));
    }

    return xplatform;
  }