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

it.tidalwave.semantic.EntityWithProperties Maven / Gradle / Ivy

There is a newer version: 1.0.13
Show newest version
/***********************************************************************************************************************
 *
 * blueBill Core - open source birding
 * Copyright (C) 2009-2011 by Tidalwave s.a.s. (http://www.tidalwave.it)
 *
 ***********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://bluebill.tidalwave.it
 * SCM: https://kenai.com/hg/bluebill~core-src
 *
 **********************************************************************************************************************/
package it.tidalwave.semantic;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import it.tidalwave.util.As;
import it.tidalwave.util.Id;
import it.tidalwave.util.Key;
import it.tidalwave.util.NotFoundException;
import it.tidalwave.util.TypeSafeHashMap;
import it.tidalwave.util.TypeSafeMap;
import org.openide.util.Lookup;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import it.tidalwave.netbeans.util.AsLookupSupport;

/***********************************************************************************************************************
 *
 * @author  Fabrizio Giudici
 * @version $Id$
 *
 **********************************************************************************************************************/
@Immutable
public class EntityWithProperties extends AsLookupSupport implements As, TypeSafeMap
  {    
    @Nonnull
    private final TypeSafeMap map;

    @Nonnull
    private final Id id; // FIXME: remove this, just pass an Identifiable in capabilities - check it's not a performance hit
    
    @Nonnull
    private final Object[] capabilities;
    
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public EntityWithProperties (final @Nonnull Id id)
      {
        super(new Object[0]);
        this.map = new TypeSafeHashMap(Collections., Object>emptyMap());
        this.id = id;
        this.capabilities = new Object[0];
//        this(id, Collections., Object>emptyMap());
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public EntityWithProperties (final @Nonnull Id id, final Object ... capabilities)
      {
        super(new Object[0]);
        this.map = new TypeSafeHashMap(Collections., Object>emptyMap());
        this.id = id;
        this.capabilities = capabilities.clone();
//        this(id, new TypeSafeHashMap(Collections., Object>emptyMap()), capabilities);
      }
    
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public EntityWithProperties (final Object ... capabilities)
      {
        super(new Object[0]);
        this.map = new TypeSafeHashMap(Collections., Object>emptyMap());
        this.id = null;
        this.capabilities = capabilities.clone();
//        this((Id)null, (Map, Object>)new TypeSafeHashMap(Collections., Object>emptyMap()), capabilities);
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    protected EntityWithProperties (final @Nonnull Id id, 
                                    final @Nonnull Map, Object> map, 
                                    final Object[] capabilities)
      {
        super(new Object[0]);
        this.map = new TypeSafeHashMap(map);
        this.id = id;
        this.capabilities = capabilities.clone();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    public Id getId()
      {
        return id;
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    public  T get (final @Nonnull Key key)
      throws NotFoundException
      {
        return map.get(key);
      }

    /*******************************************************************************************************************
     *
     * 
     *
     ******************************************************************************************************************/
    @Nonnull
    public  Collection getMultiple (final @Nonnull Key key)
      {
        try
          {
            final T object = get(key);

            if (object instanceof Collection)
              {
                return (Collection)object;
              }
            else
              {
                return Collections.singletonList(object);
              }
          }
        catch (NotFoundException e)
          {
            return Collections.emptyList();
          }
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public boolean containsKey (final @Nonnull Key item)
      {
        return map.containsKey(item);
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    public Set> getKeys()
      {
        return map.getKeys();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnegative
    public int getSize()
      {
        return map.getSize();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    public Iterator iterator()
      {
        return map.iterator();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    public  E with (final @Nonnull Key key, final @Nonnull T value)
      {
        final Map, Object> asMap = map.asMap();
        final Object oldValue = asMap.get(key);

        if (oldValue != null)
          {
            final Collection list = (oldValue instanceof Collection) ? (Collection)oldValue
                                                                           : new ArrayList();
            if (list != oldValue)
              {
                list.add((T)oldValue);
              }
            
            list.add(value);
            asMap.put(key, list);
          }
        else
          {
            asMap.put(key, value);
          }

        return clone(id, asMap, capabilities);
      }

    /*******************************************************************************************************************
     *
     * TODO: push up
     *
     ******************************************************************************************************************/
    @Nonnull
    public  E with (final @Nonnull Key key, final @Nonnull Collection values)
      {
        E o = (E)this;

        for (final T value : values)
          {
            o = (E)o.with(key, value);
          }

        return o;
      }
    
    /*******************************************************************************************************************
     *
     * So it can be overridden by subclasses.
     *
     ******************************************************************************************************************/
    @Nonnull
    protected E clone (final @Nonnull Id id,
                       final @Nonnull Map, Object> asMap,
                       final @Nonnull Object[] capabilities)
      {
        return (E)new EntityWithProperties(id, asMap, capabilities);
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    public Map, Object> asMap()
      {
        throw new UnsupportedOperationException("Not supported yet.");
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Override @Nonnull
    public String toString()
      {
        return String.format("%s@%x[%s - %s]", getClass().getSimpleName(), System.identityHashCode(this), id, map);
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Override @Nonnull
    protected Lookup createLookup() 
      {
        return (capabilities.length == 0) ? super.createLookup() 
                                          : new ProxyLookup(Lookups.fixed(capabilities), super.createLookup());
      }    
  }