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

src.com.hp.hpl.jena.util.OneToManyMap Maven / Gradle / Ivy

Go to download

Jena is a Java framework for building Semantic Web applications. It provides a programmatic environment for RDF, RDFS and OWL, SPARQL and includes a rule-based inference engine.

There is a newer version: 2.6.4
Show newest version
/*****************************************************************************
 * Source code information
 * -----------------------
 * Original author    Ian Dickinson, HP Labs Bristol
 * Author email       [email protected]
 * Package            Jena
 * Created            5 Jan 2001
 * Filename           $RCSfile: OneToManyMap.java,v $
 * Revision           $Revision: 1.15 $
 * Release status     Preview-release $State: Exp $
 *
 * Last modified on   $Date: 2008/01/02 12:07:44 $
 *               by   $Author: andy_seaborne $
 *
 * (c) Copyright 2001, 2002, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
 * See end of file for details
 *****************************************************************************/

// Package
///////////////
package com.hp.hpl.jena.util;


// Imports
///////////////
import java.util.*;

import com.hp.hpl.jena.util.iterator.NullIterator;



/**
 * An extension to a standard map that supports one-to-many mappings: that is, there
 * may be zero, one or many values corresponding to a given key.
 *
 * @author Ian Dickinson, HP Labs (email)
 * @version CVS info: $Id: OneToManyMap.java,v 1.15 2008/01/02 12:07:44 andy_seaborne Exp $
 */
public class OneToManyMap
    implements Map
{
    // Constants
    //////////////////////////////////


    // Static variables
    //////////////////////////////////


    // Instance variables
    //////////////////////////////////

    /** Encapsulated hash table stores the values */
    private Map m_table = new HashMap();


    // Constructors
    //////////////////////////////////

    /**
     * 

Construct a new empty one-to-many map

*/ public OneToManyMap() { } /** *

Construct a new one-to-many map whose contents are * initialised from the existing map.

* * @param map An existing one-to-many map */ public OneToManyMap( OneToManyMap map ) { // copy the contents of the existing map // note we can't just use the copying constructor for hashmap // as we don't want to share the arraylists that are the key values for (Iterator i = map.keySet().iterator(); i.hasNext(); ) { Object key = i.next(); for (Iterator j = map.getAll( key ); j.hasNext(); ) { put( key, j.next() ); } } } // External signature methods ////////////////////////////////// /** * Clear all entries from the map. */ public void clear() { m_table.clear(); } /** * Answer true if the map contains the given value as a key. * * @param key The key object to test for * @return True or false */ public boolean containsKey( Object key ) { return m_table.containsKey( key ); } /** * Answer true if the map contains the given object as a value * stored against any key. Note that this is quite an expensive * operation in the current implementation. * * @param value The value to test for * @return True if the value is in the map */ public boolean containsValue( Object value ) { for (Iterator values = m_table.values().iterator(); values.hasNext(); ) { Object x = values.next(); if (x.equals( value )) { return true; } else if (x instanceof List && ((List) x).contains( value )) { return true; } } return false; } /** *

Answer true if this mapping contains the pair * (key, value).

* @param key A key object * @param value A value object * @return True if key has value * as one of its values in this mapping */ public boolean contains( Object key, Object value ) { for (Iterator i = getAll( key ); i.hasNext(); ) { if (i.next().equals( value )) { return true; } } return false; } /** * Answer a set of the mappings in this map. Each member of the set will * be a Map.Entry value. * * @return A Set of the mappings as Map.Entry values. */ public Set entrySet() { Set s = CollectionFactory.createHashedSet(); for (Iterator e0 = m_table.keySet().iterator(); e0.hasNext(); ) { Object key = e0.next(); List values = (List) m_table.get( key ); // add each key-value pair to the result set for (ListIterator e1 = values.listIterator(); e1.hasNext(); ) { s.add( new Entry( key, e1.next() ) ); } } return s; } /** * Compares the specified object with this map for equality. * Returns true if the given object is also a map and the two Maps * represent the same mappings. More formally, two maps t1 and t2 represent * the same mappings if t1.entrySet().equals(t2.entrySet()). * * This ensures that the equals method works properly across different * implementations of the Map interface. * * @param o The object to be compared for equality with this map. * @return True if the specified object is equal to this map. */ public boolean equals( Object o ) { if (o instanceof java.util.Map) { return entrySet().equals( ((Map) o).entrySet() ); } else return false; } /** * Get a value for this key. Since this map is explicitly designed to * allow there to be more than one mapping per key, this method will return * an undetermined instance of the mapping. If no mapping exists, or the * selected value is null, null is returned. * * @param key The key to access the map. * @return One of the values this key corresponds to, or null. * @see #getAll */ public Object get( Object key ) { ArrayList entry = (ArrayList) m_table.get( key ); if (entry != null) { if (!entry.isEmpty()) { return entry.get( 0 ); } } // not present return null; } /** * Answer an iterator over all of the values for the given key. An iterator * is always supplied, even if the key is not present. * * @param key The key object * @return An iterator over all of the values for this key in the map */ public Iterator getAll( Object key ) { ArrayList entry = (ArrayList) m_table.get( key ); return (entry != null) ? entry.iterator() : NullIterator.instance; } /** * Returns the hash code value for this map. The hash code of a map is * defined to be the sum of the hashCodes of each entry in the map's * entrySet view. This ensures that t1.equals(t2) implies * that t1.hashCode()==t2.hashCode() for any two maps t1 and t2, * as required by the general contract of Object.hashCode */ public int hashCode() { int hc = 0; for (Iterator i = entrySet().iterator(); i.hasNext(); ) { hc ^= i.next().hashCode(); } return hc; } /** * Answer true if the map is empty of key-value mappings. * * @return True if there are no entries. */ public boolean isEmpty() { return m_table.isEmpty(); } /** * Answer a set of the keys in this map * * @return The keys of the map as a Set */ public Set keySet() { return m_table.keySet(); } /** * Associates the given value with the given key. Since this map formulation * allows many values for one key, previous associations with the key are not * lost. Consequently, the method always returns null (since the replaced value * is not defined). * * @param key The key object * @param value The value object * @return Null. */ public Object put( Object key, Object value ) { ArrayList entries = (ArrayList) m_table.get( key ); entries = entries == null ? new ArrayList() : entries; // add the new value to the list of values held against this key entries.add( value ); m_table.put( key, entries ); return null; } /** *

Put all entries from one map into this map. Tests for m being a * OneToManyMap, and, if so, copies all of the entries for each key.

* @param m The map whose contents are to be copied into this map */ public void putAll( Map m ) { boolean many = (m instanceof OneToManyMap); for (Iterator i = m.keySet().iterator(); i.hasNext(); ) { Object key = i.next(); if (many) { for (Iterator j = ((OneToManyMap) m).getAll( key ); j.hasNext(); ) { put( key, j.next() ); } } else { put( key, m.get( key ) ); } } } /** * Remove all of the associations for the given key. If only a specific * association is to be removed, use {@link #remove( java.lang.Object, java.lang.Object )} * instead. Has no effect if the key is not present in the map. Since no * single specific association with the key is defined, this method always * returns null. * * @param key All associations with this key will be removed * @return null */ public Object remove( Object key ) { m_table.remove( key ); return null; } /** *

Remove the specific association between the given key and value. Has * no effect if the association is not present in the map. If all values * for a particular key have been removed post removing this particular * association, the key will no longer appear as a key in the map.

* * @param key The key object * @param value The value object */ public void remove( Object key, Object value ) { List entries = (List) m_table.get( key ); if (entries != null) { entries.remove( value ); if (entries.isEmpty()) { m_table.remove( key ); } } } /** *

Answer the number of key-value mappings in the map

* @return The number of key-value pairs. */ public int size() { int size = 0; for (Iterator i = m_table.keySet().iterator(); i.hasNext(); ) { size += ((List) m_table.get( i.next() )).size(); } return size; } /** *

Returns a collection view of the values contained in this map. * Specifically, this will be a set, so duplicate values that appear * for multiple keys are suppressed.

* @return A set of the values contained in this map. */ public Collection values() { Set s = CollectionFactory.createHashedSet(); for (Iterator e = m_table.keySet().iterator(); e.hasNext(); ) { s.addAll( (List) m_table.get(e.next()) ); } return s; } /** *

Answer a string representation of this map. This can be quite a long string for * large maps.

*/ public String toString() { StringBuffer buf = new StringBuffer( "OneToManyMap{" ); String sep = ""; for (Iterator i = keySet().iterator(); i.hasNext(); ) { Object key = i.next(); buf.append( sep ); buf.append( key ); buf.append( "={" ); String sep1 = ""; for (Iterator j = getAll(key); j.hasNext(); ) { buf.append( sep1 ); buf.append( j.next() ); sep1=","; } buf.append("}"); sep=","; } buf.append("}"); return buf.toString(); } // Internal implementation methods ////////////////////////////////////// // Inner classes ////////////////////////////////////// ////////////////////////////////// //============================================================================== // Inner class definitions //============================================================================== /** * Helper class to implement the Map.Entry interface to enumerate entries in the map */ public static class Entry implements Map.Entry { /** My key object */ private Object m_key = null; /** My value object */ private Object m_value = null; /** * Constructor - save the key and value */ private Entry( Object key, Object value ) { m_key = key; m_value = value; } /** * Compares the specified object with this entry for equality. Returns true if the given * object is also a map entry and the two entries represent the same mapping. * More formally, two entries e1 and e2 represent the same mapping if *

         *      (e1.getKey()==null ?
         *                         e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &&
         *      (e1.getValue()==null ?
         *                         e2.getValue()==null : e1.getValue().equals(e2.getValue()))
         * 
* * This ensures that the equals method works properly across different implementations of the Map.Entry interface. * * @param x The object to compare against * @return True if the given object is equal to this Map.Entry object. */ public boolean equals( Object x ) { if (x instanceof java.util.Map.Entry) { Map.Entry e1 = (Map.Entry) x; return (e1.getKey()==null ? m_key==null : e1.getKey().equals(m_key)) && (e1.getValue()==null ? m_value == null : e1.getValue().equals(m_value)); } else return false; } /** * Answer the key for the entry * * @return The key object */ public Object getKey() { return m_key; } /** * Answer the value for the entry * * @return The value object */ public Object getValue() { return m_value; } /** * Set the value, which writes through to the map. Not implemented. */ public Object setValue( Object value ) throws UnsupportedOperationException { throw new UnsupportedOperationException( "not implemented" ); } /** * Returns the hash code value for this map entry. * The hash code of a map entry e is defined to be: * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^ * (e.getValue()==null ? 0 : e.getValue().hashCode()) * * This ensures that e1.equals(e2) implies that e1.hashCode()==e2.hashCode() for any two * Entries e1 and e2, as required by the general contract of Object.hashCode. */ public int hashCode() { return (getKey()==null ? 0 : getKey().hashCode()) ^ (getValue()==null ? 0 : getValue().hashCode()); } } } /* * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */




© 2015 - 2024 Weber Informatics LLC | Privacy Policy