/**
   * Discriminate special NF interfaces
   *
   * <ul>
   *   <li>COLLECTION: ignored, they are dynamically generated
   *   <li>CONTENT: if primitive, ignore it
   *   <li>BINDING: if primitive and DOESN'T HAVE F client interfaces, ignore it
   * </ul>
   *
   * @return true if 'special case', faslse otherwise
   */
  private boolean specialCasesForNfType(
      String itfName, PAGCMInterfaceType itfType, boolean isPrimitive) {

    // COLLECTION interfaces are ignored, because they are generated dynamically
    if (itfType.isFcCollectionItf()) {
      return true;
    }

    // CONTENT controller is not created for primitives
    if (Constants.CONTENT_CONTROLLER.equals(itfName)
        && !itfType.isFcClientItf()
        && !itfType.isInternal()
        && isPrimitive) {
      // logger.warn("Ignored NF Interface '"+ Constants.CONTENT_CONTROLLER +"' declared for
      // component '"+ this.componentParameters.getName() + "'");
      return true;
    }

    // BINDING controller is not created for primitives without client interfaces except if it has
    // an internal server interface
    if (Constants.BINDING_CONTROLLER.equals(itfName)
        && !itfType.isFcClientItf()
        && !itfType.isInternal()
        && isPrimitive) {
      if ((Utils.getClientItfTypes(this.componentParameters.getComponentType()).length == 0)
          && !hasNfInternalServerInterfaces()) {
        // logger.warn("Ignored NF Interface '"+ Constants.BINDING_CONTROLLER +"' declared for
        // component '"+ this.componentParameters.getName() + "'");
        return true;
      }
    }

    return false;
  }
  /**
   * Discriminate special controller interfaces
   *
   * <ul>
   *   <li>COLLECTION: ignored??? (TODO:check if this is needed)
   *   <li>CONTENT: if primitive, ignore it
   *   <li>BINDING: if primitive and DOESN'T HAVE F client interfaces, ignore it
   *   <li>Avoid duplicates
   * </ul>
   *
   * @param controllerName
   * @param itfType
   * @param isPrimitive
   * @return
   */
  private boolean specialCasesForController(
      String controllerName,
      PAGCMInterfaceType itfType,
      boolean isPrimitive,
      String controllersConfigFileLocation) {

    // COLLECTION interfaces are ignored, because they are generated dynamically (and an object
    // controller shouldn't be a collection, right?)
    // if(itfType.isFcCollectionItf()) {
    //	return true;
    // }

    // CONTENT controller is not created for primitives
    if (Constants.CONTENT_CONTROLLER.equals(controllerName)
        && !itfType.isFcClientItf()
        && !itfType.isInternal()
        && isPrimitive) {
      // logger.warn("Ignored controller '"+ Constants.CONTENT_CONTROLLER +"' declared for component
      // '"+ this.componentParameters.getName() + "' in file: "+ controllersConfigFileLocation);
      return true;
    }

    // BINDING controller is not created for primitives without client interfaces except if it has
    // an internal server interface
    if (Constants.BINDING_CONTROLLER.equals(controllerName)
        && !itfType.isFcClientItf()
        && !itfType.isInternal()
        && isPrimitive) {
      if ((Utils.getClientItfTypes(this.componentParameters.getComponentType()).length == 0)
          && !hasNfInternalServerInterfaces()) {
        // logger.warn("Ignored controller '"+ Constants.BINDING_CONTROLLER +"' declared for
        // component '"+ this.componentParameters.getName() + "' in file: "+
        // controllersConfigFileLocation);
        return true;
      }
    }

    // Controller interface had already been declared (f.e., in the NF Type). Do not create this
    // controller.
    if (existsNfInterface(controllerName)) {
      // logger.warn("Controller interface '"+ controllerName +"' already created. Ignoring this
      // controller.");
      return true;
    }

    return false;
  }
  private void addControllers(Map<String, String> controllersConfiguration) {
    // create the interface references tables
    // the size is the addition of :
    // - 1 for the current ItfRef (that is at the same time a binding controller, lifecycle
    // controller,
    // content controller and name controller
    // - the number of client functional interfaces
    // - the number of server functional interfaces
    // ArrayList interface_references_list = new ArrayList(1
    // +componentType.getFcInterfaceTypes().length+controllersConfiguration.size());
    this.nfItfs = new HashMap<String, Interface>(1 + controllersConfiguration.size());

    // add controllers
    // Enumeration controllersInterfaces = controllersConfiguration.propertyNames();
    Iterator<String> iteratorOnControllers = controllersConfiguration.keySet().iterator();
    Class<?> controllerClass = null;
    AbstractPAController currentController;
    PAInterface currentInterface = null;
    Class<?> controllerItf;
    Vector<InterfaceType> nfType = new Vector<InterfaceType>();
    while (iteratorOnControllers.hasNext()) {
      String controllerItfName = iteratorOnControllers.next();
      try {
        controllerItf = Class.forName(controllerItfName);
        controllerClass = Class.forName(controllersConfiguration.get(controllerItf.getName()));
        Constructor<?> controllerClassConstructor =
            controllerClass.getConstructor(new Class<?>[] {Component.class});
        currentController =
            (AbstractPAController) controllerClassConstructor.newInstance(new Object[] {this});
        currentInterface =
            RepresentativeInterfaceClassGenerator.instance()
                .generateControllerInterface(
                    currentController.getFcItfName(),
                    this,
                    (PAGCMInterfaceType) currentController.getFcItfType());
        ((StubObject) currentInterface).setProxy(this.proxy);

      } catch (Exception e) {
        logger.error(
            "could not create controller "
                + controllersConfiguration.get(controllerItfName)
                + " : "
                + e.getMessage());
        continue;
      }

      if (BindingController.class.isAssignableFrom(controllerClass)) {
        if ((this.componentParameters.getHierarchicalType().equals(Constants.PRIMITIVE)
            && (Utils.getClientItfTypes(this.componentParameters.getComponentType()).length == 0)
            && !hasNfInternalServerInterfaces())) {
          if (logger.isDebugEnabled()) {
            logger.debug(
                "user component class of this component does not have any client interface. It will have no BindingController");
          }
          continue;
        }
      }
      if (ContentController.class.isAssignableFrom(controllerClass)) {
        if (Constants.PRIMITIVE.equals(this.componentParameters.getHierarchicalType())) {
          // no content controller here
          continue;
        }
      }
      if (currentInterface != null) {
        this.nfItfs.put(currentController.getFcItfName(), currentInterface);
        nfType.add((InterfaceType) currentInterface.getFcItfType());
      }
    }

    try { // Setting the real NF type, as some controllers may not be generated
      Component boot = Utils.getBootstrapComponent();
      PAGCMTypeFactory type_factory = Utils.getPAGCMTypeFactory(boot);
      InterfaceType[] fItfTypes =
          ((PAComponentType) this.componentParameters.getComponentType()).getFcInterfaceTypes();
      InterfaceType[] nfItfTypes = nfType.toArray(new InterfaceType[] {});
      this.componentParameters.setComponentType(type_factory.createFcType(fItfTypes, nfItfTypes));
    } catch (Exception e) {
      e.printStackTrace();
      logger.warn("NF type could not be set");
    }
  }