public MapPlotResourceManager() {
   for (PlotLineStyle plotLineStyle : PlotLineStyle.values()) {
     for (PlotLineColor plotLineColor : PlotLineColor.values()) {
       preparedLineDefs.add(PlotLineDef.newInstance(plotLineColor.getColor(), plotLineStyle));
     }
   }
 }
/** User: serso Date: 1/19/13 Time: 12:48 AM */
public class MapPlotResourceManager implements PlotResourceManager {

  @Nonnull
  private Map<PlotLineDef, List<PlotLineDef>> registeredLineDefsMap =
      new HashMap<PlotLineDef, List<PlotLineDef>>();

  @Nonnull
  private final List<PlotLineDef> preparedLineDefs =
      new ArrayList<PlotLineDef>(PlotLineStyle.values().length * PlotLineColor.values().length);

  public MapPlotResourceManager() {
    for (PlotLineStyle plotLineStyle : PlotLineStyle.values()) {
      for (PlotLineColor plotLineColor : PlotLineColor.values()) {
        preparedLineDefs.add(PlotLineDef.newInstance(plotLineColor.getColor(), plotLineStyle));
      }
    }
  }

  @Nonnull
  @Override
  public PlotLineDef generateAndRegister() {
    synchronized (this) {
      for (PlotLineDef lineDef : preparedLineDefs) {
        final List<PlotLineDef> registeredLineDefs = registeredLineDefsMap.get(lineDef);
        if (registeredLineDefs == null || registeredLineDefs.isEmpty()) {
          register(lineDef);
          return lineDef;
        }
      }

      return preparedLineDefs.get(0);
    }
  }

  private void addLineDef(@Nonnull final PlotLineDef toBeAdded) {
    if (!Thread.holdsLock(this)) throw new AssertionError();

    List<PlotLineDef> registeredLineDefs = registeredLineDefsMap.get(toBeAdded);
    if (registeredLineDefs == null) {
      registeredLineDefs = new ArrayList<PlotLineDef>();
      registeredLineDefsMap.put(toBeAdded, registeredLineDefs);
    }

    try {
      Iterables.find(
          registeredLineDefs,
          new Predicate<PlotLineDef>() {
            @Override
            public boolean apply(@Nullable PlotLineDef lineDef) {
              return lineDef == toBeAdded;
            }
          });

      // already added

    } catch (NoSuchElementException e) {
      registeredLineDefs.add(toBeAdded);
    }
  }

  private void removeLineDef(@Nonnull final PlotLineDef toBeRemoved) {
    if (!Thread.holdsLock(this)) throw new AssertionError();

    List<PlotLineDef> registeredLineDefs = registeredLineDefsMap.get(toBeRemoved);

    if (registeredLineDefs != null) {
      Iterables.removeIf(
          registeredLineDefs,
          new Predicate<PlotLineDef>() {
            @Override
            public boolean apply(@Nullable PlotLineDef lineDef) {
              return lineDef == toBeRemoved;
            }
          });

      if (registeredLineDefs.isEmpty()) {
        registeredLineDefsMap.remove(toBeRemoved);
      }

    } else {
      registeredLineDefsMap.remove(toBeRemoved);
    }
  }

  @Override
  public void register(@Nonnull PlotLineDef lineDef) {
    synchronized (this) {
      addLineDef(lineDef);
    }
  }

  @Override
  public void unregister(@Nonnull PlotLineDef lineDef) {
    synchronized (this) {
      removeLineDef(lineDef);
    }
  }

  @Override
  public void unregisterAll() {
    synchronized (this) {
      registeredLineDefsMap.clear();
    }
  }
}