/*
  * @see ASTVisitor#visit(EnumDeclaration)
  * @since 3.0
  */
 @Override
 public boolean visit(EnumDeclaration node) {
   if (node.getJavadoc() != null) {
     node.getJavadoc().accept(this);
   }
   printModifiers(node.modifiers());
   this.fBuffer.append("enum "); // $NON-NLS-1$
   node.getName().accept(this);
   this.fBuffer.append(" "); // $NON-NLS-1$
   if (!node.superInterfaceTypes().isEmpty()) {
     this.fBuffer.append("implements "); // $NON-NLS-1$
     for (Iterator<Type> it = node.superInterfaceTypes().iterator(); it.hasNext(); ) {
       Type t = it.next();
       t.accept(this);
       if (it.hasNext()) {
         this.fBuffer.append(", "); // $NON-NLS-1$
       }
     }
     this.fBuffer.append(" "); // $NON-NLS-1$
   }
   this.fBuffer.append("{"); // $NON-NLS-1$
   for (Iterator<EnumConstantDeclaration> it = node.enumConstants().iterator(); it.hasNext(); ) {
     EnumConstantDeclaration d = it.next();
     d.accept(this);
     // enum constant declarations do not include punctuation
     if (it.hasNext()) {
       // enum constant declarations are separated by commas
       this.fBuffer.append(", "); // $NON-NLS-1$
     }
   }
   if (!node.bodyDeclarations().isEmpty()) {
     this.fBuffer.append("; "); // $NON-NLS-1$
     for (Iterator<BodyDeclaration> it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
       BodyDeclaration d = it.next();
       d.accept(this);
       // other body declarations include trailing punctuation
     }
   }
   this.fBuffer.append("}"); // $NON-NLS-1$
   return false;
 }
  @Override
  public boolean visit(EnumDeclaration node) {

    if (node.isPackageMemberTypeDeclaration() || node.isMemberTypeDeclaration()) {
      ITypeBinding typeBinding = node.resolveBinding();
      if (typeBinding != null) {
        ApiEnum apiClass = new ApiEnum(typeBinding.getQualifiedName());
        apiClass.setInterface(typeBinding.isInterface());
        this.setModifiers(apiClass, node);

        this.classMap.put(typeBinding, apiClass);

        if (!this.attachmentMap.containsKey(node.getRoot())) {
          Attachment attachment =
              new Attachment(
                  typeBinding.getQualifiedName().concat(".java"),
                  node.getRoot().toString().getBytes());
          this.attachmentMap.put(node.getRoot(), attachment);
        }

        List<MethodDeclaration> declarations = new LinkedList<MethodDeclaration>();
        for (Object o : node.bodyDeclarations()) {
          if (o instanceof MethodDeclaration) {
            declarations.add((MethodDeclaration) o);
          }
        }

        for (final MethodDeclaration declaration : declarations) {

          final List<Expression> invocations = new LinkedList<Expression>();
          this.methodDeclarationHandler(declaration, apiClass);

          InvocationVisitor visitor = new InvocationVisitor();
          declaration.accept(visitor);

          invocations.addAll(visitor.invocations);

          // Parte de extracao de exemplos, se não houver invocações eu pulo esta parte
          if (invocations.isEmpty()) {
            return super.visit(node);
          } else {
            // Faço a extração de exemplos para cada invocação em separado
            Set<ApiMethod> methodsInvocations = new HashSet<ApiMethod>();
            for (Expression mi : invocations) {
              ApiMethod apiMethod = this.mapInvocations.get(mi);
              methodsInvocations.add(apiMethod);
              Example newExample =
                  makeExample(
                      declaration, Collections.singleton(mi), Collections.singletonList(apiMethod));
              if (newExample != null) {
                this.examples.add(newExample);
              }
            }

            // Se houver mais de uma invocacao faço o slicing com sementes multiplas
            if (invocations.size() > 1) {
              // Itero sobre os conjuntos das regras
              Iterator<Set<ApiMethod>> it = this.methodSets.iterator();
              while (it.hasNext()) {
                // Podando conjuntos
                Set<ApiMethod> s = it.next();
                if (s.size() > methodsInvocations.size()) {
                  break;
                } else {
                  // Se as invocacoes identificadas envolvem metodos desejados eu processo
                  if (methodsInvocations.containsAll(s)) {
                    List<ApiMethod> methods = new ArrayList<ApiMethod>();
                    Set<Expression> invocationsTemp = new HashSet<Expression>();
                    for (Expression mi : invocations) {
                      ApiMethod relatedMethod = this.mapInvocations.get(mi);
                      if (s.contains(relatedMethod)) {
                        methods.add(relatedMethod);
                        invocationsTemp.add(mi);
                      }
                    }
                    Example newExample = makeExample(declaration, invocationsTemp, methods);
                    if (newExample != null) {
                      this.examples.add(newExample);
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

    return super.visit(node);
  }