/**
   * Set annotation preferences of users for a given project such as window size, annotation
   * layers,... reading from the file system.
   *
   * @param aUsername The {@link User} for whom we need to read the preference (preferences are
   *     stored per user)
   * @param aRepositoryService the repository service.
   * @param aAnnotationService the annotation service.
   * @param aBModel The {@link BratAnnotatorModel} that will be populated with preferences from the
   *     file
   * @param aMode the mode.
   * @throws BeansException hum?
   * @throws IOException hum?
   */
  public static void setAnnotationPreference(
      String aUsername,
      RepositoryService aRepositoryService,
      AnnotationService aAnnotationService,
      BratAnnotatorModel aBModel,
      Mode aMode)
      throws BeansException, IOException {
    AnnotationPreference preference = new AnnotationPreference();
    BeanWrapper wrapper = new BeanWrapperImpl(preference);
    // get annotation preference from file system
    try {
      Properties props = aRepositoryService.loadUserSettings(aUsername, aBModel.getProject());
      for (Entry<Object, Object> entry : props.entrySet()) {
        String property = entry.getKey().toString();
        int index = property.lastIndexOf(".");
        String propertyName = property.substring(index + 1);
        String mode = property.substring(0, index);
        if (wrapper.isWritableProperty(propertyName) && mode.equals(aMode.getName())) {
          if (AnnotationPreference.class.getDeclaredField(propertyName).getGenericType()
              instanceof ParameterizedType) {
            List<String> value =
                Arrays.asList(
                    StringUtils.replaceChars(entry.getValue().toString(), "[]", "").split(","));
            if (!value.get(0).equals("")) {
              wrapper.setPropertyValue(propertyName, value);
            }
          } else {
            wrapper.setPropertyValue(propertyName, entry.getValue());
          }
        }
      }
      aBModel.setPreferences(preference);

      // Get tagset using the id, from the properties file
      aBModel.getAnnotationLayers().clear();
      if (preference.getAnnotationLayers() != null) {
        for (Long id : preference.getAnnotationLayers()) {
          aBModel.getAnnotationLayers().add(aAnnotationService.getLayer(id));
        }
      } else {
        // If no layer preferences are defined, then just assume all layers are enabled
        List<AnnotationLayer> layers = aAnnotationService.listAnnotationLayer(aBModel.getProject());
        aBModel.setAnnotationLayers(layers);
      }
    }
    // no preference found
    catch (Exception e) {
      // If no layer preferences are defined, then just assume all layers are enabled
      List<AnnotationLayer> layers = aAnnotationService.listAnnotationLayer(aBModel.getProject());
      aBModel.setAnnotationLayers(layers);
    }
  }
  @Override
  protected String getDocumentData() {
    if (!dirty) {
      return docData;
    }

    dirty = false;

    // Clear the rendered document
    docData = EMPTY_DOC;

    // Check if a document is set
    if (getModelObject() == null) {
      return docData;
    }

    // Get CAS from the repository
    JCas jCas = null;
    try {
      jCas = repository.readAnnotationCas(getModelObject());
    } catch (IOException | DataRetrievalFailureException e) {
      LOG.error("Unable to read annotation document", e);
      error("Unable to read annotation document: " + ExceptionUtils.getRootCauseMessage(e));
    }
    // Generate BRAT object model from CAS
    GetDocumentResponse response = new GetDocumentResponse();
    response.setText(jCas.getDocumentText());

    BratAnnotatorModel bratAnnotatorModel = new BratAnnotatorModel();
    SpanAdapter.renderTokenAndSentence(jCas, response, bratAnnotatorModel);

    Map<String[], Queue<String>> colorQueues = new HashMap<>();
    for (AnnotationLayer layer : bratAnnotatorModel.getAnnotationLayers()) {
      if (layer.getName().equals(Token.class.getName())) {
        continue;
      }
      List<AnnotationFeature> features = annotationService.listAnnotationFeature(layer);
      List<AnnotationFeature> invisibleFeatures = new ArrayList<AnnotationFeature>();
      for (AnnotationFeature feature : features) {
        if (!feature.isVisible()) {
          invisibleFeatures.add(feature);
        }
      }
      features.removeAll(invisibleFeatures);

      ColoringStrategy coloringStrategy =
          ColoringStrategy.getBestStrategy(
              annotationService, layer, bratAnnotatorModel.getPreferences(), colorQueues);

      getAdapter(annotationService, layer)
          .render(jCas, features, response, bratAnnotatorModel, coloringStrategy);
    }

    // Serialize BRAT object model to JSON
    try {
      StringWriter out = new StringWriter();
      JsonGenerator jsonGenerator =
          JSONUtil.getJsonConverter().getObjectMapper().getFactory().createGenerator(out);
      jsonGenerator.writeObject(response);
      docData = out.toString();
    } catch (IOException e) {
      error(ExceptionUtils.getRootCauseMessage(e));
    }

    return docData;
  }