/**
  * Method called by the processAllColorSpace if the ColorSpace to check is Separation. Because
  * this kind of ColorSpace can have an alternate color space, the processAllColorSpace is called
  * to check this alternate color space. (Indexed, Separation, DeviceN and Pattern can't be a Base
  * color space)
  *
  * @param colorSpace the color space object to check.
  */
 protected void processSeparationColorSpace(PDColorSpace colorSpace) {
   try {
     COSBase cosAlt = ((COSArray) colorSpace.getCOSObject()).getObject(2);
     PDColorSpace altCol = PDColorSpace.create(cosAlt);
     if (altCol != null) {
       ColorSpaces acs = ColorSpaces.valueOf(altCol.getName());
       switch (acs) {
         case Separation:
         case DeviceN:
         case Pattern:
         case Indexed:
         case I:
           context.addValidationError(
               new ValidationError(
                   ERROR_GRAPHIC_INVALID_COLOR_SPACE_ALTERNATE,
                   acs.getLabel() + " color space can't be used as alternate color space"));
           break;
         default:
           processAllColorSpace(altCol);
       }
     }
   } catch (IOException e) {
     context.addValidationError(
         new ValidationError(
             ERROR_GRAPHIC_INVALID_COLOR_SPACE,
             "Unable to read Separation color space : " + e.getMessage(),
             e));
   }
 }
  /**
   * Method called by the validate method. According to the ColorSpace, a specific ColorSpace method
   * is called.
   *
   * @param colorSpace the color space object to check.
   */
  protected final void processAllColorSpace(PDColorSpace colorSpace) {
    ColorSpaces cs = ColorSpaces.valueOf(colorSpace.getName());

    switch (cs) {
      case DeviceRGB:
      case RGB:
        processRGBColorSpace(colorSpace);
        break;
      case DeviceCMYK:
      case CMYK:
        processCYMKColorSpace(colorSpace);
        break;
      case CalRGB:
      case CalGray:
      case Lab:
        processCalibratedColorSpace(colorSpace);
        break;
      case DeviceGray:
      case G:
        processGrayColorSpace(colorSpace);
        break;
      case ICCBased:
        processICCBasedColorSpace(colorSpace);
        break;
      case DeviceN:
        processDeviceNColorSpace(colorSpace);
        break;
      case Indexed:
      case I:
        processIndexedColorSpace(colorSpace);
        break;
      case Separation:
        processSeparationColorSpace(colorSpace);
        break;
      case Pattern:
        processPatternColorSpace(colorSpace);
        break;
      default:
        context.addValidationError(
            new ValidationError(
                ERROR_GRAPHIC_INVALID_UNKNOWN_COLOR_SPACE,
                cs.getLabel() + " is unknown as ColorSpace"));
    }
  }
 /**
  * Method called by the processAllColorSpace if the ColorSpace to check is Indexed. Because this
  * kind of ColorSpace can have a Base color space, the processAllColorSpace is called to check
  * this base color space. (Indexed and Pattern can't be a Base color space)
  *
  * @param colorSpace the color space object to check.
  */
 protected void processIndexedColorSpace(PDColorSpace colorSpace) {
   PDIndexed indexed = (PDIndexed) colorSpace;
   PDColorSpace based = indexed.getBaseColorSpace();
   ColorSpaces cs = ColorSpaces.valueOf(based.getName());
   if (cs == ColorSpaces.Indexed || cs == ColorSpaces.I) {
     context.addValidationError(
         new ValidationError(
             ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED,
             "Indexed color space can't be used as Base color space"));
     return;
   }
   if (cs == ColorSpaces.Pattern) {
     context.addValidationError(
         new ValidationError(
             ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED,
             "Pattern color space can't be used as Base color space"));
     return;
   }
   processAllColorSpace(based);
 }
  /**
   * Method called by the processAllColorSpace if the ColorSpace to check is a ICCBased color space.
   * Because this kind of ColorSpace can have alternate color space, the processAllColorSpace is
   * called to check this alternate color space. (Pattern is forbidden as Alternate Color Space)
   *
   * @param colorSpace the color space object to check.
   */
  protected void processICCBasedColorSpace(PDColorSpace colorSpace) {
    PDICCBased iccBased = (PDICCBased) colorSpace;
    try {
      ICC_Profile.getInstance(iccBased.getPDStream().createInputStream());
      PDColorSpace altpdcs = iccBased.getAlternateColorSpace();
      if (altpdcs != null) {
        ColorSpaces altCsId = ColorSpaces.valueOf(altpdcs.getName());
        if (altCsId == ColorSpaces.Pattern) {
          context.addValidationError(
              new ValidationError(
                  ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN,
                  "Pattern is forbidden as AlternateColorSpace of a ICCBased"));
        }

        /*
         * According to the ISO-19005-1:2005
         *
         * A conforming reader shall render ICCBased colour spaces as specified by the ICC specification,
         * and shall not use the Alternate colour space specified in an ICC profile stream dictionary
         *
         * We don't check the alternate ColorSpaces
         */
      }
    } catch (IllegalArgumentException e) {
      // this is not a ICC_Profile
      context.addValidationError(
          new ValidationError(
              ERROR_GRAPHIC_INVALID_COLOR_SPACE_ICCBASED,
              "ICCBased color space is invalid: " + e.getMessage(),
              e));
    } catch (IOException e) {
      context.addValidationError(
          new ValidationError(
              ERROR_GRAPHIC_INVALID_COLOR_SPACE,
              "Unable to read ICCBase color space: " + e.getMessage(),
              e));
    }
  }