/**
   * Saves a tile layer info into the given metadata map using the old legacy metadata elements. For
   * unit testing only.
   *
   * @param source
   * @param metadata
   */
  public static void save(GeoServerTileLayerInfo source, MetadataMap metadata) {
    final boolean enabled = source.isEnabled();
    final int gutter = source.getGutter();
    final Set<XMLGridSubset> cachedGridSubsets = source.getGridSubsets();
    final int metaTilingX = source.getMetaTilingX();
    final int metaTilingY = source.getMetaTilingY();
    final Set<String> mimeFormats = source.getMimeFormats();
    final Boolean autoCacheStyles = source.isAutoCacheStyles();
    final Set<String> cachedStyles = source.cachedStyles();
    final boolean inMemoryCached = source.isInMemoryCached();

    metadata.put(CONFIG_KEY_ENABLED, Boolean.valueOf(enabled));
    metadata.put(CONFIG_KEY_GUTTER, Integer.valueOf(gutter));
    Collection<String> subsetNames = new ArrayList<String>();
    for (XMLGridSubset s : cachedGridSubsets) {
      subsetNames.add(s.getGridSetName());
    }
    metadata.put(CONFIG_KEY_GRIDSETS, marshalList(subsetNames));
    metadata.put(CONFIG_KEY_METATILING_X, Integer.valueOf(metaTilingX));
    metadata.put(CONFIG_KEY_METATILING_Y, Integer.valueOf(metaTilingY));
    metadata.put(CONFIG_KEY_FORMATS, marshalList(mimeFormats));
    metadata.put(CONFIG_KEY_AUTO_CACHE_STYLES, autoCacheStyles);
    metadata.put(CONFIG_KEY_IN_MEMORY_CACHED, inMemoryCached);

    if (cachedStyles.size() > 0) {
      metadata.put(CONFIG_KEY_CACHED_STYLES, marshalList(cachedStyles));
    } else {
      metadata.remove(CONFIG_KEY_CACHED_STYLES);
    }
  }
  public void testLoadLayerInfoAutoCacheStyles() {
    GeoServerTileLayerInfo info = defaultVectorInfo;
    info.setAutoCacheStyles(true);

    LayerInfoImpl layer = mockLayer("testLayer", "style1", "style2");
    assertNull(LegacyTileLayerInfoLoader.load(layer));

    LegacyTileLayerInfoLoader.save(info, layer.getMetadata());

    GeoServerTileLayerInfo actual;
    actual = LegacyTileLayerInfoLoader.load(layer);

    TileLayerInfoUtil.setCachedStyles(info, "default", ImmutableSet.of("style1", "style2"));

    info.setId(layer.getId());
    info.setName(tileLayerName(layer));
    assertEquals(info, actual);

    layer.setDefaultStyle(null);
    TileLayerInfoUtil.setCachedStyles(info, null, ImmutableSet.of("style1", "style2"));

    actual = LegacyTileLayerInfoLoader.load(layer);
    assertEquals(ImmutableSet.of("style1", "style2"), actual.cachedStyles());
  }
  /**
   * Handles changes of interest to GWC on a {@link LayerInfo}.
   *
   * <ul>
   *   <li>If the name of the default style changed, then the layer's cache for the default style is
   *       truncated. This method doesn't check if the contents of the styles are equal. That is
   *       handled by {@link CatalogStyleChangeListener} whenever a style is modified.
   *   <li>If the tile layer is {@link GeoServerTileLayerInfo#isAutoCacheStyles() auto caching
   *       styles} and the layerinfo's "styles" list changed, the tile layer's STYLE parameter
   *       filter is updated to match the actual list of layer styles and any removed style is
   *       truncated.
   * </ul>
   *
   * @param changedProperties
   * @param oldValues
   * @param newValues
   * @param li
   * @param tileLayerInfo
   */
  private void handleLayerInfoChange(
      final List<String> changedProperties,
      final List<Object> oldValues,
      final List<Object> newValues,
      final LayerInfo li,
      final GeoServerTileLayerInfo tileLayerInfo) {

    checkNotNull(tileLayerInfo);

    final String layerName = tileLayerName(li);

    boolean save = false;

    final String defaultStyle;

    /*
     * If default style name changed
     */
    if (changedProperties.contains("defaultStyle")) {
      final int propIndex = changedProperties.indexOf("defaultStyle");
      final StyleInfo oldStyle = (StyleInfo) oldValues.get(propIndex);
      final StyleInfo newStyle = (StyleInfo) newValues.get(propIndex);

      final String oldStyleName = oldStyle.getName();
      defaultStyle = newStyle.getName();
      if (!Objects.equal(oldStyleName, defaultStyle)) {
        save = true;
        log.info(
            "Truncating default style for layer "
                + layerName
                + ", as it changed from "
                + oldStyleName
                + " to "
                + defaultStyle);
        mediator.truncateByLayerAndStyle(layerName, oldStyleName);
      }
    } else {
      StyleInfo styleInfo = li.getDefaultStyle();
      defaultStyle = styleInfo == null ? null : styleInfo.getName();
    }

    if (tileLayerInfo.isAutoCacheStyles()) {
      Set<String> styles = new HashSet<String>();
      for (StyleInfo s : li.getStyles()) {
        styles.add(s.getName());
      }
      ImmutableSet<String> cachedStyles = tileLayerInfo.cachedStyles();
      if (!styles.equals(cachedStyles)) {
        // truncate no longer existing cached styles
        Set<String> notCachedAnyMore = Sets.difference(cachedStyles, styles);
        for (String oldCachedStyle : notCachedAnyMore) {
          log.info(
              "Truncating cached style "
                  + oldCachedStyle
                  + " of layer "
                  + layerName
                  + " as it's no longer one of the layer's styles");
          mediator.truncateByLayerAndStyle(layerName, oldCachedStyle);
        }
        // reset STYLES parameter filter
        final boolean createParamIfNotExists = true;
        TileLayerInfoUtil.updateStringParameterFilter(
            tileLayerInfo, "STYLES", createParamIfNotExists, defaultStyle, styles);
        save = true;
      }
    }

    if (save) {
      GridSetBroker gridSetBroker = mediator.getGridSetBroker();
      GeoServerTileLayer tileLayer = new GeoServerTileLayer(li, gridSetBroker, tileLayerInfo);
      mediator.save(tileLayer);
    }
  }