///////////////////////////////////////////////////////////////////////////////////////////////////
  //	main
  ///////////////////////////////////////////////////////////////////////////////////////////////////
  public static void main(String[] args) throws IOException {

    final FileWriter okWriter =
        new FileWriter(
            new File("d:/temp_dev/opendata/servicios.csv")); // fichero al que escribir los datos
    final FileWriter errWriter =
        new FileWriter(
            new File(
                "d:/temp_dev/opendata/servicios_err.log")); // fichero al que escribir los datos
    try {
      okWriter.write(ServiceData.csvHEAD()); // write the header

      // [1] Construir la query
      R01MSearchFilterForContent qry = _buildQuery();

      log.debug("[SearchQuery]: " + qry.toCriteriaString());

      // [2] Inicializar la sesión
      R01MSearchSession.resultItemStreamForQuery(qry)
          .map(
              new Func1<R01MSearchResultItem, ServiceData>() {
                @Override
                public ServiceData call(final R01MSearchResultItem item) {
                  try {
                    return _resultItemToServiceData(item);
                  } catch (IOException ioEx) {
                    throw OnErrorThrowable.from(ioEx);
                  }
                }
              })
          .subscribe(
              new Observer<ServiceData>() {
                @Override
                public void onCompleted() {
                  System.out.println("---->End!");
                }

                @Override
                public void onNext(final ServiceData serviceData) {
                  _writeRow(okWriter, serviceData);
                }

                @Override
                public void onError(final Throwable th) {
                  _writeError(errWriter, th);
                }
              });
    } catch (Exception ex) {
      ex.printStackTrace(System.out);
    } finally {
      try {
        okWriter.close();
        errWriter.close();
      } catch (IOException ioEx) {
        ioEx.printStackTrace(System.out);
      }
    }
  }
  /**
   * Procesar los resultados de búsqueda: acceder a algunos datos: - MetaDatos comunes como el
   * nombre del contenido y versión idiomática - MetaDatos específicos: XML del tipo de contenido
   *
   * @param items los items a procesar
   * @return
   */
  private static ServiceData _resultItemToServiceData(final R01MSearchResultItem item)
      throws IOException {
    ServiceData itemData = new ServiceData();

    // Algunos metaDatos comunes
    // -------------------------
    itemData.setContentName(item.getContentName());
    itemData.setLang(item.getDocumentLanguage());
    itemData.setLangVersionName(item.getDocumentName());

    // Algunos meta-datos relevantes dependientes del tipo de contenido
    // pero que son devueltos por el buscador
    // ----------------------------------------------------------------
    Map<String, ?> indexedMD = item.getDocumentMetaData();
    itemData.setProcedureStatus(
        indexedMD != null ? indexedMD.get("procedureStatus").toString() : null);

    // MetaDatos específicos disponibles en un XML que hay que descargar de euskadi.net
    // --------------------------------------------------------------------------------
    String dataFileXML = _downloadDataFileXML(item);
    if (dataFileXML != null) itemData.setDataFileXML(dataFileXML);

    // Assets reusables (ZIP con el contenido)
    // ---------------------------------------
    Map<String, Path> assets = item.getReusableAssets();
    if (CollectionUtils.hasData(assets)) itemData.setReusableAssets(assets);

    return itemData;
  }