All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.codecamp.messages.shared.bundle.MessageBundleManager Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
package de.codecamp.messages.shared.bundle;

import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toSet;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;

import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;

import de.codecamp.messages.shared.conf.ProjectConf;


public class MessageBundleManager
{

  public static final String PROPERTIES_EXT = "properties";


  private final ProjectConf projectConf;

  private final FileSystemAdapter fileSystem;

  private final D bundleDir;

  private final boolean flatBundleDir = false;

  private Map> bundleFiles = new HashMap<>();


  public MessageBundleManager(ProjectConf projectConf, FileSystemAdapter fileSystem)
  {
    if (projectConf == null)
      throw new IllegalArgumentException("projectConf must not be null");

    this.projectConf = projectConf;
    this.fileSystem = fileSystem;

    this.bundleDir = fileSystem.getDirectory(projectConf.getBundleDir());
    if (bundleDir == null)
      throw new IllegalStateException("Bundle directory not found or not configured correctly.");

    List files;
    try
    {
      files = fileSystem.listFiles(getBundleDir(), !flatBundleDir);
    }
    catch (Exception ex)
    {
      String msg = "Failed to list all message bundle files in '%s'.";
      msg = String.format(msg, getBundleDir());
      throw new BundleException(msg, ex);
    }
    for (F file : files)
    {
      if (fileSystem.getFileName(file).endsWith("." + PROPERTIES_EXT)
          && toBundleFileCoordinates(fileSystem, bundleDir, file) != null)
      {
        prepareBundleFile(file, false);
      }
    }
  }


  public static  BundleFileCoordinates toBundleFileCoordinates(String fileName)
  {
    String name = StringUtils.removeEnd(fileName, "." + PROPERTIES_EXT);

    int i = StringUtils.lastIndexOf(name, ".");
    if (i < 0)
      i = 0;
    i = StringUtils.indexOf(name, "_", i);

    String bundleName;
    Locale locale;
    if (i >= 0)
    {
      bundleName = StringUtils.substring(name, 0, i);
      String localeString = name.substring(i + 1);
      try
      {
        locale = LocaleUtils.toLocale(localeString);
      }
      catch (IllegalArgumentException ex)
      {
        return null;
      }
    }
    else
    {
      bundleName = name;
      locale = Locale.ROOT;
    }

    bundleName = bundleName.replace("/", ".").replace("\\", ".");

    return new BundleFileCoordinates(bundleName, locale);
  }

  private static  BundleFileCoordinates toBundleFileCoordinates(
      FileSystemAdapter fileSystem, D bundleDir, F file)
  {
    return toBundleFileCoordinates(fileSystem.getRelativeFilePath(bundleDir, file));
  }


  private D getBundleDir()
  {
    return bundleDir;
  }

  public Set getBundleNames()
  {
    return bundleFiles.values().stream().map(BundleFile::getBundleName)
        .filter(bundleName -> !projectConf.getIgnoredBundles().contains(bundleName))
        .collect(toSet());
  }

  public boolean bundleExists(String bundleName)
  {
    return getBundleNames().contains(bundleName);
  }

  public boolean isReadOnly(String bundleName)
  {
    return projectConf.getIgnoredBundles().contains(bundleName);
  }

  public BundleFile getBundleFile(String bundleName, Locale locale)
  {
    return getBundleFile(bundleName, locale, false);
  }

  public BundleFile getBundleFile(String bundleName, Locale locale, boolean create)
  {
    BundleFile bundleFile = bundleFiles.values().stream().filter(
        file -> file.getBundleName().equals(bundleName) && Objects.equals(file.getLocale(), locale))
        .findAny().orElse(null);

    if (bundleFile == null && create)
    {
      String bundleFileName = bundleName.replace('.', '/');

      if (!Locale.ROOT.equals(locale))
        bundleFileName += "_" + locale.toString();

      bundleFileName += "." + PROPERTIES_EXT;

      F file = fileSystem.getFile(getBundleDir(), bundleFileName);
      bundleFile = prepareBundleFile(file, true);
    }
    else if (bundleFile != null)
    {
      bundleFile.ensureLoaded();
    }

    return bundleFile;
  }

  public BundleFile getBundleFileAt(F fileLocation)
  {
    BundleFile bundleFile = bundleFiles.get(fileLocation);

    if (bundleFile != null)
      bundleFile.ensureLoaded();

    return bundleFile;
  }

  public Set> getBundleFiles()
  {
    return getBundleFiles(false);
  }

  public Set> getBundleFiles(boolean includeIgnored)
  {
    Stream> bundleStream = bundleFiles.values().stream();
    if (!includeIgnored)
    {
      bundleStream = bundleStream
          .filter(file -> !projectConf.getIgnoredBundles().contains(file.getBundleName()));
    }

    return bundleStream.filter(bf ->
    {
      try
      {
        bf.ensureLoaded();
      }
      catch (BundleException ex)
      {
        return false;
      }
      return true;
    }).sorted().collect(toCollection(() -> new LinkedHashSet<>()));
  }


  public Set> getBundleFiles(String bundleName)
  {
    return bundleFiles.values().stream()
        .filter(file -> Objects.equals(file.getBundleName(), bundleName))
        .peek(BundleFile::ensureLoaded).collect(toSet());
  }

  public Set> getBundleFiles(Locale locale)
  {
    return bundleFiles.values().stream().filter(file -> Objects.equals(file.getLocale(), locale))
        .peek(BundleFile::ensureLoaded).collect(toSet());
  }

  private BundleFile prepareBundleFile(F bundleFilePath, boolean load)
  {
    BundleFile bundleFile = bundleFiles.get(bundleFilePath);
    if (bundleFile == null)
    {
      BundleFileCoordinates coordinates =
          toBundleFileCoordinates(fileSystem, bundleDir, bundleFilePath);
      if (coordinates == null)
      {
        throw new BundleException(String.format("Not a message bundle file: %s", bundleFilePath));
      }

      bundleFile = new BundleFile<>(fileSystem, bundleFilePath, projectConf.getBundleEncoding(),
          coordinates, fileSystem.getDisplayPath(getBundleDir(), bundleFilePath));

      if (projectConf.getIgnoredBundles().contains(bundleFile.getBundleName()))
        bundleFile.setReadOnly(true);

      if (load)
        bundleFile.ensureLoaded();

      bundleFiles.put(bundleFilePath, bundleFile);
    }
    return bundleFile;
  }

  public String getMessage(String messageKey, Locale locale)
  {
    String targetBundleName =
        projectConf.toTargetBundleName(messageKey).orElseThrow(() -> new IllegalArgumentException(
            "No target bundle configured for message key code '" + messageKey + "'."));

    return getBundleFile(targetBundleName, locale, true).getMessage(messageKey);
  }

  public void setMessage(String messageKey, Locale locale, String message)
  {
    String targetBundleName =
        projectConf.toTargetBundleName(messageKey).orElseThrow(() -> new IllegalArgumentException(
            "No target bundle configured for message key code '" + messageKey + "'."));

    getBundleFile(targetBundleName, locale, true).setMessage(messageKey, message);
  }

  public void removeMessage(String messageKey, Locale locale)
  {
    String targetBundleName =
        projectConf.toTargetBundleName(messageKey).orElseThrow(() -> new IllegalArgumentException(
            "No target bundle configured for message key code '" + messageKey + "'."));

    BundleFile bundleFile = getBundleFile(targetBundleName, locale, false);
    if (bundleFile != null)
      bundleFile.removeMessage(messageKey);
  }

  public void removeMessage(String messageKey)
  {
    String targetBundleName = projectConf.toTargetBundleName(messageKey).orElse(null);
    if (targetBundleName == null)
      return;

    boolean found = false;

    for (BundleFile bundleFile : getBundleFiles(targetBundleName))
    {
      String oldMessage = bundleFile.removeMessage(messageKey);
      if (oldMessage != null)
        found = true;
    }

    if (!found)
    {
      for (BundleFile bundleFile : getBundleFiles())
      {
        if (bundleFile.getBundleName().equals(targetBundleName))
          continue;

        bundleFile.removeMessage(messageKey);
      }
    }
  }


  public void save()
    throws BundleException
  {
    save(false);
  }

  public void save(boolean forceForSorting)
    throws BundleException
  {
    for (BundleFile bundleFile : bundleFiles.values())
    {
      if (!bundleFile.isLoaded() || bundleFile.isReadOnly())
        continue;

      if (bundleFile.isEmpty())
        bundleFile.delete();
      else
        bundleFile.save(forceForSorting && bundleFile.needsSorting());
    }
  }


  public static class BundleFileCoordinates
  {

    private final String bundleName;

    private final Locale locale;


    public BundleFileCoordinates(String bundleName, Locale locale)
    {
      this.bundleName = bundleName;
      this.locale = locale;
    }


    public String getBundleName()
    {
      return bundleName;
    }

    public Locale getLocale()
    {
      return locale;
    }

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy