@Override
    public Void visitType(TypeElement element, Environment env) {
        if(element.getKind() == ElementKind.INTERFACE || element.getKind() == ElementKind.CLASS) {
            ClassDefinition definition = env.getClassDefinition();
            
            switch(element.getKind()) {
                case INTERFACE:
                    definition.setElementType(ElementType.INTERFACE);
                    break;
                case CLASS:
                    definition.setElementType(ElementType.CLASS);
                    break;
            }
            
            //if the element have some super-interfaces, visit them at first.
            for (TypeMirror superType : element.getInterfaces()) {
                Element superInterface = env.getProcessingEnvironment().getTypeUtils().asElement(superType);
                env.setLevel(env.getLevel() + 1);
                if(interfaceFilter.canHandle(superType)) {
                    this.visit(superInterface, env);
                }
                env.setLevel(env.getLevel() - 1);
            }

            if(env.getLevel() == 0) {
                String[] splited = splitPackageName(element.getQualifiedName().toString());
                if(splited == null) {
                    throw new IllegalStateException("the qualified name of the element " + element.toString() + " was a null or an empty string.");
                }
                definition.setPackage(splited[0]);
                definition.setClassName(splited[1]);
                definition.addTypeParameters(element.getTypeParameters().toArray(new TypeParameterElement[0]));
            }
        }
        return super.visitType(element, env);
    }