MetadataSupport.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * blueMarine II: Semantic Media Centre
  5.  * http://tidalwave.it/projects/bluemarine2
  6.  *
  7.  * Copyright (C) 2015 - 2021 by Tidalwave s.a.s. (http://tidalwave.it)
  8.  *
  9.  * *********************************************************************************************************************
  10.  *
  11.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  12.  * the License. You may obtain a copy of the License at
  13.  *
  14.  *     http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  17.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations under the License.
  19.  *
  20.  * *********************************************************************************************************************
  21.  *
  22.  * git clone https://bitbucket.org/tidalwave/bluemarine2-src
  23.  * git clone https://github.com/tidalwave-it/bluemarine2-src
  24.  *
  25.  * *********************************************************************************************************************
  26.  */
  27. package it.tidalwave.bluemarine2.model.spi;

  28. import javax.annotation.Nonnull;
  29. import javax.annotation.Nullable;
  30. import java.util.Collections;
  31. import java.util.HashMap;
  32. import java.util.Map;
  33. import java.util.Optional;
  34. import java.util.Set;
  35. import java.nio.file.Path;
  36. import it.tidalwave.util.Key;
  37. import it.tidalwave.bluemarine2.model.MediaItem;
  38. import java.util.function.Function;
  39. import lombok.Getter;
  40. import lombok.RequiredArgsConstructor;
  41. import lombok.ToString;
  42. import lombok.extern.slf4j.Slf4j;

  43. /***********************************************************************************************************************
  44.  *
  45.  * @author  Fabrizio Giudici
  46.  *
  47.  **********************************************************************************************************************/
  48. @RequiredArgsConstructor @ToString(of = "properties") @Slf4j
  49. public class MetadataSupport implements MediaItem.Metadata
  50.   {
  51.     @Getter @Nonnull
  52.     protected final Path path;

  53.     @Nonnull
  54.     protected Optional<Function<Key<?>, MediaItem.Metadata>> fallback;

  55.     protected final Map<Key<?>, Object> properties = new HashMap<>();

  56.     /*******************************************************************************************************************
  57.      *
  58.      *
  59.      *
  60.      ******************************************************************************************************************/
  61.     public MetadataSupport (@Nonnull final Path path)
  62.       {
  63.         this(path, Optional.empty());
  64.       }

  65.     /*******************************************************************************************************************
  66.      *
  67.      * {@inheritDoc}
  68.      *
  69.      ******************************************************************************************************************/
  70.     @Override @Nonnull
  71.     public <T> Optional<T> get (@Nonnull final Key<T> key)
  72.       {
  73.         return properties.containsKey(key) ? Optional.ofNullable((T)properties.get(key))
  74.                                            : fallback.flatMap(fb -> fb.apply(key).get(key));
  75.       }

  76.     /*******************************************************************************************************************
  77.      *
  78.      * {@inheritDoc}
  79.      *
  80.      ******************************************************************************************************************/
  81.     @Override @Nonnull
  82.     public <T> T getAll (@Nonnull final Key<T> key)
  83.       {
  84.         final T list = (T)properties.get(key);
  85.         return (list != null) ? list :
  86.                 fallback.flatMap(fb -> fb.apply(key).get(key)).orElse((T)Collections.emptyList());
  87.       }

  88.     /*******************************************************************************************************************
  89.      *
  90.      * {@inheritDoc}
  91.      *
  92.      ******************************************************************************************************************/
  93.     @Override
  94.     public boolean containsKey (@Nonnull final Key<?> key)
  95.       {
  96.         return properties.containsKey(key);
  97.       }

  98.     /*******************************************************************************************************************
  99.      *
  100.      * {@inheritDoc}
  101.      *
  102.      ******************************************************************************************************************/
  103.     @Override @Nonnull
  104.     public Set<Key<?>> getKeys()
  105.       {
  106.         return Collections.unmodifiableSet(properties.keySet());
  107.       }

  108.     /*******************************************************************************************************************
  109.      *
  110.      * {@inheritDoc}
  111.      *
  112.      ******************************************************************************************************************/
  113.     @Override @Nonnull
  114.     public Set<Map.Entry<Key<?>, ?>> getEntries()
  115.       {
  116.         return Collections.unmodifiableSet(properties.entrySet());
  117.       }

  118.     /*******************************************************************************************************************
  119.      *
  120.      * {@inheritDoc}
  121.      *
  122.      ******************************************************************************************************************/
  123.     @Override @Nonnull
  124.     public <T> MediaItem.Metadata with (@Nonnull final Key<T> key, @Nonnull final T value)
  125.       {
  126.         final MetadataSupport clone = new MetadataSupport(path, fallback);
  127.         clone.properties.putAll(this.properties);
  128.         clone.put(key, value);

  129.         if (value instanceof ITunesComment)
  130.           {
  131.             clone.put(CDDB, ((ITunesComment) value).getCddb());
  132.           }

  133.         return clone;
  134.       }

  135.     /*******************************************************************************************************************
  136.      *
  137.      * {@inheritDoc}
  138.      *
  139.      ******************************************************************************************************************/
  140.     @Override @Nonnull
  141.     public MediaItem.Metadata withFallback (@Nonnull final Function<Key<?>, MediaItem.Metadata> fallback)
  142.       {
  143.         final MetadataSupport clone = new MetadataSupport(path, Optional.of(fallback));
  144.         clone.properties.putAll(this.properties);
  145.         return clone;
  146.       }

  147.     /*******************************************************************************************************************
  148.      *
  149.      * {@inheritDoc}
  150.      *
  151.      ******************************************************************************************************************/
  152.     @Override @Nonnull
  153.     public <T> MediaItem.Metadata with (@Nonnull final Key<T> key, @Nonnull final Optional<T> value)
  154.       {
  155.         return value.map(t -> with(key, t)).orElse(this);
  156.       }

  157.     /*******************************************************************************************************************
  158.      *
  159.      * FIXME: remove this, make it truly immutable.
  160.      *
  161.      ******************************************************************************************************************/
  162.     protected <V> void put (@Nonnull final Key<V> key, @Nullable final V value)
  163.       {
  164.         if (value != null)
  165.           {
  166.             properties.put(key, value);
  167.           }
  168.       }
  169.   }