/**
   * Return a list of installed languages in the provided application module.
   *
   * @param moduleName the module name to search for installed languages.
   * @return a list with the available languages.
   */
  @Override
  public List<I18n> getInstalledLanguages(String moduleName) {

    final LogicalPath resourcesPath = LogicalPath.getInstance(Path.SRC_MAIN_RESOURCES, moduleName);
    final String targetDirectory = getPathResolver().getIdentifier(resourcesPath, "");

    // Create list for installed languages
    List<I18n> installedLanguages = new ArrayList<I18n>();

    // Get all available languages
    Set<I18n> supportedLanguages = getI18nSupport().getSupportedLanguages();
    for (I18n i18n : supportedLanguages) {
      String messageBundle =
          String.format("messages_%s.properties", i18n.getLocale().getLanguage());
      String bundlePath =
          String.format(
              "%s%s%s", targetDirectory, AntPathMatcher.DEFAULT_PATH_SEPARATOR, messageBundle);

      if (getFileManager().exists(bundlePath)) {
        installedLanguages.add(i18n);
      }
    }

    // Always add English language as default
    installedLanguages.add(new EnglishLanguage());

    return Collections.unmodifiableList(installedLanguages);
  }
  /**
   * Add labels to all installed languages
   *
   * @param moduleName
   * @param labels
   */
  @Override
  public void addOrUpdateLabels(String moduleName, final Map<String, String> labels) {
    final LogicalPath resourcesPath = LogicalPath.getInstance(Path.SRC_MAIN_RESOURCES, moduleName);
    final String targetDirectory = getPathResolver().getIdentifier(resourcesPath, "");

    Set<I18n> supportedLanguages = getI18nSupport().getSupportedLanguages();
    for (I18n i18n : supportedLanguages) {
      String messageBundle =
          String.format("messages_%s.properties", i18n.getLocale().getLanguage());
      String bundlePath =
          String.format(
              "%s%s%s", targetDirectory, AntPathMatcher.DEFAULT_PATH_SEPARATOR, messageBundle);

      if (getFileManager().exists(bundlePath)) {
        getPropFilesManager().addProperties(resourcesPath, messageBundle, labels, true, false);
      }
    }

    // Allways update english message bundles
    getPropFilesManager().addProperties(resourcesPath, "messages.properties", labels, true, false);
  }
  @Override
  public void installLanguage(final I18n language, final boolean useAsDefault, final Pom module) {

    // Check if provided module match with application modules features
    Validate.isTrue(
        getTypeLocationService().hasModuleFeature(module, ModuleFeatureName.APPLICATION),
        "ERROR: Provided module doesn't match with application modules features. "
            + "Execute this operation again and provide a valid application module.");

    Validate.notNull(language, "ERROR: You should provide a valid language code.");

    if (language.getLocale() == null) {
      LOGGER.warning("ERROR: Provided language is not valid.");
      return;
    }

    final LogicalPath resourcesPath =
        LogicalPath.getInstance(Path.SRC_MAIN_RESOURCES, module.getModuleName());

    final String targetDirectory = getPathResolver().getIdentifier(resourcesPath, "");

    // Getting message.properties file
    String messageBundle = "";

    if (language.getLocale().equals(Locale.ENGLISH)) {
      messageBundle = targetDirectory + "messages.properties";
    } else {
      messageBundle =
          targetDirectory
              .concat("messages_")
              .concat(language.getLocale().getLanguage().concat(".properties"));
    }

    if (!getFileManager().exists(messageBundle)) {
      InputStream inputStream = null;
      OutputStream outputStream = null;
      try {
        inputStream = language.getMessageBundle();
        outputStream = getFileManager().createFile(messageBundle).getOutputStream();
        IOUtils.copy(inputStream, outputStream);
      } catch (final Exception e) {
        throw new IllegalStateException(
            "Encountered an error during copying of message bundle MVC JSP addon.", e);
      } finally {
        IOUtils.closeQuietly(inputStream);
        IOUtils.closeQuietly(outputStream);
      }
    }

    // Install flag
    final String flagGraphic =
        targetDirectory
            .concat("static/public/img/")
            .concat(language.getLocale().getLanguage())
            .concat(".png");
    if (!getFileManager().exists(flagGraphic)) {
      InputStream inputStream = null;
      OutputStream outputStream = null;
      try {
        inputStream = language.getFlagGraphic();
        outputStream = getFileManager().createFile(flagGraphic).getOutputStream();
        IOUtils.copy(inputStream, outputStream);
      } catch (final Exception e) {
        throw new IllegalStateException(
            "Encountered an error during copying of flag graphic for MVC JSP addon.", e);
      } finally {
        IOUtils.closeQuietly(inputStream);
        IOUtils.closeQuietly(outputStream);
      }
    }

    // Update @WebMvcConfiguration annotation defining defaultLanguage
    // attribute
    if (useAsDefault) {

      // Obtain all existing configuration classes annotated with
      // @RooWebMvcConfiguration
      Set<ClassOrInterfaceTypeDetails> configurationClasses =
          getTypeLocationService()
              .findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_WEB_MVC_CONFIGURATION);

      for (ClassOrInterfaceTypeDetails configurationClass : configurationClasses) {
        // If configuration class is located in the provided module
        if (configurationClass.getType().getModule().equals(module.getModuleName())) {
          ClassOrInterfaceTypeDetailsBuilder cidBuilder =
              new ClassOrInterfaceTypeDetailsBuilder(configurationClass);
          AnnotationMetadataBuilder annotation =
              cidBuilder.getDeclaredTypeAnnotation(RooJavaType.ROO_WEB_MVC_CONFIGURATION);
          annotation.addStringAttribute("defaultLanguage", language.getLocale().getLanguage());

          // Update configuration class
          getTypeManagementService().createOrUpdateTypeOnDisk(cidBuilder.build());
        }
      }

      LOGGER.log(
          Level.INFO,
          String.format(
              "INFO: Default language of your project has been changed to %s.",
              language.getLanguage()));
    }

    // Get all controllers and update its message bundles
    Set<ClassOrInterfaceTypeDetails> controllers =
        getTypeLocationService()
            .findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_CONTROLLER);
    for (ClassOrInterfaceTypeDetails controller : controllers) {
      getMetadataService().evictAndGet(ControllerMetadata.createIdentifier(controller));
    }

    // Add application property
    getApplicationConfigService()
        .addProperty(
            module.getModuleName(), "spring.messages.fallback-to-system-locale", "false", "", true);
  }