/**
   * Builds the FSTModel of the feature project and creates a list of all directives with valid
   * colors
   *
   * @return the directive list
   */
  private void createDirectiveList() {
    directiveMap.clear();
    validDirectiveList.clear();
    FSTModel model = project.getFSTModel();
    if (model == null) {
      composer.buildFSTModel();
      model = project.getFSTModel();
    }
    if (model == null) {
      return;
    }

    int index = 0;
    for (FSTFeature fstFeature : model.getFeatures()) {
      for (FSTRole role : fstFeature.getRoles()) {
        if (file.equals(role.getFile())) {
          for (FSTDirective dir : role.getDirectives()) {
            directiveMap.put(dir.getId(), dir);
            index++;
          }
        }
      }
    }

    for (int i = 0; i < index; i++) {
      FSTDirective dir = directiveMap.get(i);
      if (dir != null && ColorList.isValidColor(dir.getColor())) {
        validDirectiveList.add(dir);
      }
    }
  }
  /** Creates Annotations for FOP */
  private void createFOPAnnotations() throws BadLocationException {
    AnnotationModelEvent event = new AnnotationModelEvent(this);
    FSTModel model = project.getFSTModel();

    if (model == null) {
      composer.buildFSTModel();
      model = project.getFSTModel();
    }
    if (model == null) {
      return;
    }

    clear();

    if (file.getParent() instanceof IFolder) {
      if (isInBuildFolder((IFolder) file.getParent())) {
        /* annotations for generated files */
        FSTClass clazz = model.getClass(model.getAbsoluteClassName(file));
        if (clazz == null) {
          return;
        }
        if (!clazz.hasComposedLines) {
          clazz.hasComposedLines = true;
          composer.postCompile(null, file);
        }
        for (FSTFeature fstFeature : model.getFeatures()) {
          FSTRole role = clazz.getRole(fstFeature.getName());
          if (role == null) {
            continue;
          }
          for (FSTMethod m : role.getAllMethods()) {
            createFOPComposedAnnotations(event, fstFeature, m);
          }
          for (FSTField f : role.getAllFields()) {
            createFOPComposedAnnotations(event, fstFeature, f);
          }
        }
      } else {
        /* annotations for source files */
        String featureName = getFeature((IFolder) file.getParent());
        if (featureName != null) {
          FSTFeature fstFeature = model.getFeature(featureName);
          if (fstFeature != null) {
            // bar at the left of the editor
            final int color = fstFeature.getColor();
            for (int line = 0; line < document.getNumberOfLines(); line++) {
              Position position = new Position(document.getLineOffset(line), 1);
              ColorAnnotation cafh =
                  new ColorAnnotation(color, position, ColorAnnotation.TYPE_IMAGE);
              cafh.setText(fstFeature.getName());
              annotations.add(cafh);
              event.annotationAdded(cafh);
            }
          }
        }
      }
    }
  }
  /**
   * Builds the FSTModel of the feature project and creates a list of all directives with valid
   * colors
   *
   * @return the directive list
   */
  private void createDirectiveList() {
    directiveMap.clear();
    validDirectiveList.clear();
    FSTModel model = project.getFSTModel();
    if (model == null || model.getClasses().isEmpty()) {
      composer.buildFSTModel();
      model = project.getFSTModel();
    }
    if (model == null) {
      return;
    }

    for (FSTFeature fstFeature : model.getFeatures()) {
      for (FSTRole role : fstFeature.getRoles()) {
        if (file.equals(role.getFile())) {
          for (FSTDirective dir : role.getDirectives()) {
            directiveMap.put(dir.getId(), dir);
            validDirectiveList.add(dir);
          }
        }
      }
    }
  }
 /**
  * Creates Annotations for FOP Composed File
  *
  * @param event
  * @param fstFeature
  * @param m
  * @throws BadLocationException
  */
 private void createFOPComposedAnnotations(
     AnnotationModelEvent event, FSTFeature fstFeature, RoleElement<?> m)
     throws BadLocationException {
   if (m.getComposedLine() <= 0) {
     return;
   }
   int startline = m.getComposedLine() - 1;
   int endline = m.getComposedLine() + m.getMethodLength() - 1;
   int lineOffset = document.getLineOffset(startline);
   int length = 0;
   for (int line = startline; line <= endline; line++) {
     length += document.getLineLength(line);
     // bar at the left of the editor
     Position methodposition =
         new Position(document.getLineOffset(line), document.getLineLength(line));
     ColorAnnotation cafh =
         new ColorAnnotation(
             m.getRole().getFeature().getColor(), methodposition, ColorAnnotation.TYPE_IMAGE);
     cafh.setText(m.getRole().getFeature().getName());
     annotations.add(cafh);
     event.annotationAdded(cafh);
   }
   Position methodposition = new Position(lineOffset, length);
   // bar at the right of the editor
   ColorAnnotation cafho =
       new ColorAnnotation(
           m.getRole().getFeature().getColor(), methodposition, ColorAnnotation.TYPE_OVERVIEW);
   cafho.setText(m.getRole().getFeature().getName());
   annotations.add(cafho);
   event.annotationAdded(cafho);
   if (highlighting) {
     // background colors
     ColorAnnotation cafhh =
         new ColorAnnotation(
             m.getRole().getFeature().getColor(), methodposition, ColorAnnotation.TYPE_HIGHLIGHT);
     cafhh.setText(fstFeature.getName());
     annotations.add(cafhh);
     event.annotationAdded(cafhh);
   }
 }
  /**
   * Propagates all markers of the given file
   *
   * @param markers
   * @param file
   */
  private void propagateMarkers(AbstractCollection<IMarker> markers, IFile file) {
    if (!file.exists()) {
      return;
    }

    String content = getFileContent(file);
    LinkedList<FSTField> fields = new LinkedList<FSTField>();
    LinkedList<FSTMethod> methods = new LinkedList<FSTMethod>();
    IFeatureProject project = CorePlugin.getFeatureProject(file);
    if (project == null) {
      return;
    }
    FSTModel model = project.getFSTModel();
    if (model == null) {
      return;
    }
    for (FSTFeature f : model.getFeaturesMap().values()) {
      TreeMap<String, FSTClass> z = f.getClasses();
      String fileName = file.getName();
      if (z.containsKey(fileName)) {
        FSTClass c = z.get(fileName);
        for (FSTField field : c.getFields()) {
          fields.add(field);
        }
        for (FSTMethod method : c.getMethods()) {
          methods.add(method);
        }
      }
    }
    setElementLines(content, fields, methods);

    for (IMarker marker : markers) {
      if (!marker.exists()) {
        continue;
      }

      if (marker.getAttribute(IMarker.MESSAGE, "").startsWith("The import")) {
        propagateUnsupportedMarker(marker, file);
        continue;
      }
      int markerLine = marker.getAttribute(IMarker.LINE_NUMBER, -1);
      if (markerLine == -1) {
        continue;
      }

      boolean propagated = false;
      for (FSTField f : fields) {
        if (f.getEndLine() == -1) {
          continue;
        }
        int composedLine = f.getComposedLine();
        if (markerLine >= composedLine
            && markerLine <= composedLine + (f.getEndLine() - f.getBeginLine())) {
          propagateMarker(marker, f.getOwnFile(), f.getBeginLine() + markerLine - composedLine);
          propagated = true;
          break;
        }
      }

      if (propagated) {
        continue;
      }

      for (FSTMethod m : methods) {
        if (m.getEndLine() == -1) {
          continue;
        }
        int composedLine = m.getComposedLine();
        if (markerLine >= composedLine
            && markerLine <= composedLine + (m.getEndLine() - m.getBeginLine())) {
          propagateMarker(
              marker, m.getOwnFile(), m.getBeginLine() + markerLine - m.getComposedLine());
          propagated = true;
          break;
        }
      }

      if (propagated) {
        continue;
      }

      propagateUnsupportedMarker(marker, file);
    }
  }