From d35bdc2df6fe2b1def39aeba38e1bf7ea502541d Mon Sep 17 00:00:00 2001 From: Michael Christen Date: Mon, 5 Dec 2011 23:37:49 +0100 Subject: [PATCH] removed npe --- .../net/yacy/kelondro/blob/BEncodedHeap.java | 285 +++++++++++------- 1 file changed, 172 insertions(+), 113 deletions(-) diff --git a/source/net/yacy/kelondro/blob/BEncodedHeap.java b/source/net/yacy/kelondro/blob/BEncodedHeap.java index 2be6f34e2..d1e4072f0 100644 --- a/source/net/yacy/kelondro/blob/BEncodedHeap.java +++ b/source/net/yacy/kelondro/blob/BEncodedHeap.java @@ -50,16 +50,19 @@ import net.yacy.kelondro.util.BEncoder; import net.yacy.kelondro.util.FileUtils; /** - * store a table of properties (instead of fixed-field entries) - * this is realized using blobs and BEncoded property lists + * store a table of properties (instead of fixed-field entries) this is realized using blobs and BEncoded + * property lists */ -public class BEncodedHeap implements Map>, Iterable>> { +public class BEncodedHeap implements Map>, + Iterable>> +{ private Heap table; private final LinkedHashSet columnames; /** * produce or open a properties table + * * @param location the file * @param keylength length of access keys * @param ordering ordering on the keys @@ -67,22 +70,21 @@ public class BEncodedHeap implements Map>, Iterable< * @throws IOException */ public BEncodedHeap( - final File location, - final int keylength, - final ByteOrder ordering, - final int buffermax) throws IOException { + final File location, + final int keylength, + final ByteOrder ordering, + final int buffermax) throws IOException { this.table = new Heap(location, keylength, ordering, buffermax); this.columnames = new LinkedHashSet(); } /** * convenience method to open a properies table + * * @param location the file * @param keylength length of access keys */ - public BEncodedHeap( - final File location, - final int keylength) throws IOException { + public BEncodedHeap(final File location, final int keylength) throws IOException { this.table = new Heap(location, keylength, NaturalOrder.naturalOrder, 100); this.columnames = new LinkedHashSet(); } @@ -91,45 +93,54 @@ public class BEncodedHeap implements Map>, Iterable< return Base64Order.enhancedCoder.encodeSubstring(Digest.encodeMD5Raw(key), this.table.keylength); } - private static class EntryIter implements Iterator>> { + private static class EntryIter implements Iterator>> + { HeapReader.entries iter; + public EntryIter(final File location, final int keylen) throws IOException { this.iter = new HeapReader.entries(location, keylen); } + @Override public boolean hasNext() { return this.iter.hasNext(); } + @Override public Entry> next() { final Map.Entry entry = this.iter.next(); final Map map = b2m(entry.getValue()); return new b2mEntry(entry.getKey(), map); } + @Override public void remove() { throw new UnsupportedOperationException(); } } - public static class b2mEntry implements Map.Entry> { + public static class b2mEntry implements Map.Entry> + { private final byte[] s; - private Map b; + private Map b; public b2mEntry(final byte[] s, final Map b) { this.s = s; this.b = b; } + @Override public byte[] getKey() { return this.s; } + @Override public Map getValue() { return this.b; } + @Override public Map setValue(final Map value) { final Map b1 = this.b; this.b = value; @@ -138,15 +149,21 @@ public class BEncodedHeap implements Map>, Iterable< } private static Map b2m(final byte[] b) { - if (b == null) return null; + if ( b == null ) { + return null; + } //System.out.println("b = " + UTF8.String(b)); final BDecoder decoder = new BDecoder(b); final BObject bobj = decoder.parse(); - if (bobj.getType() != BDecoder.BType.dictionary) return null; + if ( bobj == null || bobj.getType() != BDecoder.BType.dictionary ) { + return null; + } final Map map = bobj.getMap(); final Map m = new HashMap(); - for (final Map.Entry entry: map.entrySet()) { - if (entry.getValue().getType() != BDecoder.BType.string) continue; + for ( final Map.Entry entry : map.entrySet() ) { + if ( entry.getValue().getType() != BDecoder.BType.string ) { + continue; + } m.put(entry.getKey(), entry.getValue().getString()); } return m; @@ -154,6 +171,7 @@ public class BEncodedHeap implements Map>, Iterable< /** * the map is stored inside a file; this method may return the file + * * @return the file where the map is stored */ public File getFile() { @@ -162,8 +180,10 @@ public class BEncodedHeap implements Map>, Iterable< /** * Retur the number of key-value mappings in this map. + * * @return the number of entries mappings in this map */ + @Override public int size() { return this.table.size(); } @@ -171,12 +191,14 @@ public class BEncodedHeap implements Map>, Iterable< /** * return true if the table is empty */ + @Override public boolean isEmpty() { return this.table.size() == 0; } /** * check if a row with given key exists in the table + * * @param name * @return true if the row exists */ @@ -185,20 +207,23 @@ public class BEncodedHeap implements Map>, Iterable< } /** - * check if a row with given key exists in the table - * This method is here to implement the Map interface + * check if a row with given key exists in the table This method is here to implement the Map interface + * * @param name * @return true if the row exists */ + @Override public boolean containsKey(final Object key) { - if (key instanceof byte[]) return containsKey((byte[]) key); + if ( key instanceof byte[] ) { + return containsKey((byte[]) key); + } return false; } /** - * the containsValue method cannot be used in this method - * and is only here to implement the Map interface + * the containsValue method cannot be used in this method and is only here to implement the Map interface */ + @Override public boolean containsValue(final Object value) { // this method shall not be used because it is not appropriate for this kind of data throw new UnsupportedOperationException(); @@ -206,6 +231,7 @@ public class BEncodedHeap implements Map>, Iterable< /** * get a map from the table + * * @param name * @return the map if one found or NULL if no entry exists or the entry is corrupt * @throws RowSpaceExceededException @@ -213,32 +239,37 @@ public class BEncodedHeap implements Map>, Iterable< */ public Map get(final byte[] pk) throws IOException, RowSpaceExceededException { final byte[] b = this.table.get(pk); - if (b == null) return null; + if ( b == null ) { + return null; + } return b2m(b); } /** - * get a map from the table - * this method is here to implement the Map interface + * get a map from the table this method is here to implement the Map interface + * * @param name * @return the map if one found or NULL if no entry exists or the entry is corrupt */ + @Override public Map get(final Object key) { - if (key instanceof byte[]) + if ( key instanceof byte[] ) { try { return get((byte[]) key); - } catch (final IOException e) { + } catch ( final IOException e ) { Log.logException(e); return null; - } catch (final RowSpaceExceededException e) { + } catch ( final RowSpaceExceededException e ) { Log.logException(e); return null; } + } return null; } /** * convenience method to get a value from a map + * * @param pk * @param key * @return the value @@ -247,14 +278,17 @@ public class BEncodedHeap implements Map>, Iterable< */ public byte[] getProp(final byte[] pk, final String key) throws IOException, RowSpaceExceededException { final byte[] b = this.table.get(pk); - if (b == null) return null; + if ( b == null ) { + return null; + } final Map map = b2m(b); return map.get(key); } /** - * select all rows from a table where a given matcher matches with elements in a given row - * this method makes a full-table scan of the whole table + * select all rows from a table where a given matcher matches with elements in a given row this method + * makes a full-table scan of the whole table + * * @param columnName the name of the column where the matcher shall match * @param columnMatcher the matcher for the elements of the column * @return a set of primary keys where the matcher matched @@ -265,50 +299,59 @@ public class BEncodedHeap implements Map>, Iterable< Map prop; byte[] val; final Set pks = new TreeSet(this.table.ordering); - while (i.hasNext()) { + while ( i.hasNext() ) { row = i.next(); prop = row.getValue(); val = prop.get(columnName); - if (val != null) { - if (columnMatcher.matcher(UTF8.String(val)).matches()) pks.add(row.getKey()); + if ( val != null ) { + if ( columnMatcher.matcher(UTF8.String(val)).matches() ) { + pks.add(row.getKey()); + } } } return pks; } /** - * select one row from a table where a given matcher matches with elements in a given row - * this method stops the full-table scan as soon as a first matcher was found + * select one row from a table where a given matcher matches with elements in a given row this method + * stops the full-table scan as soon as a first matcher was found + * * @param columnName the name of the column where the matcher shall match * @param columnMatcher the matcher for the elements of the column * @return the row where the matcher matched the given column */ - public Map.Entry> selectOne(final String columnName, final Pattern columnMatcher) { + public Map.Entry> selectOne( + final String columnName, + final Pattern columnMatcher) { final Iterator>> i = iterator(); Map.Entry> row; Map prop; byte[] val; - while (i.hasNext()) { + while ( i.hasNext() ) { row = i.next(); prop = row.getValue(); val = prop.get(columnName); - if (val != null) { - if (columnMatcher.matcher(UTF8.String(val)).matches()) return row; + if ( val != null ) { + if ( columnMatcher.matcher(UTF8.String(val)).matches() ) { + return row; + } } } return null; } /** - * insert a map into the table - * this method shall be used in exchange of the get method if the - * previous entry value is not needed. + * insert a map into the table this method shall be used in exchange of the get method if the previous + * entry value is not needed. + * * @param name * @param map * @throws RowSpaceExceededException * @throws IOException */ - public void insert(final byte[] pk, final Map map) throws RowSpaceExceededException, IOException { + public void insert(final byte[] pk, final Map map) + throws RowSpaceExceededException, + IOException { final byte[] b = BEncoder.encode(BEncoder.transcode(map)); this.table.insert(pk, b); this.columnames.addAll(map.keySet()); @@ -320,9 +363,11 @@ public class BEncodedHeap implements Map>, Iterable< this.columnames.add(key); } - public void update(final byte[] pk, final Map map) throws RowSpaceExceededException, IOException { + public void update(final byte[] pk, final Map map) + throws RowSpaceExceededException, + IOException { final Map entry = this.get(pk); - if (entry == null) { + if ( entry == null ) { insert(pk, map); } else { entry.putAll(map); @@ -330,9 +375,11 @@ public class BEncodedHeap implements Map>, Iterable< } } - public void update(final byte[] pk, final String key, final byte[] value) throws RowSpaceExceededException, IOException { + public void update(final byte[] pk, final String key, final byte[] value) + throws RowSpaceExceededException, + IOException { Map entry = this.get(pk); - if (entry == null) { + if ( entry == null ) { entry = new HashMap(); entry.put(key, value); insert(pk, entry); @@ -344,20 +391,22 @@ public class BEncodedHeap implements Map>, Iterable< /** * insert a map into the table + * * @param name * @param map */ - public Map put(final byte[] pk, final Map map) { + @Override + public Map put(final byte[] pk, final Map map) { try { final Map entry = this.get(pk); final byte[] b = BEncoder.encode(BEncoder.transcode(map)); this.table.insert(pk, b); this.columnames.addAll(map.keySet()); return entry; - } catch (final IOException e) { + } catch ( final IOException e ) { Log.logException(e); return null; - } catch (final RowSpaceExceededException e) { + } catch ( final RowSpaceExceededException e ) { Log.logException(e); return null; } @@ -365,6 +414,7 @@ public class BEncodedHeap implements Map>, Iterable< /** * delete a map from the table + * * @param name * @throws IOException */ @@ -374,6 +424,7 @@ public class BEncodedHeap implements Map>, Iterable< /** * delete a map from the table + * * @param name * @throws RowSpaceExceededException * @throws IOException @@ -384,77 +435,83 @@ public class BEncodedHeap implements Map>, Iterable< return value; } + @Override public Map remove(final Object key) { - if (key instanceof byte[]) + if ( key instanceof byte[] ) { try { return remove((byte[]) key); - } catch (final IOException e) { + } catch ( final IOException e ) { Log.logException(e); return null; - } catch (final RowSpaceExceededException e) { + } catch ( final RowSpaceExceededException e ) { Log.logException(e); return null; } + } return null; } /** * Copy all the mappings from the specified map to this map. - * + * * @param m mappings to be stored in this map */ + @Override public void putAll(final Map> map) { - for (final Map.Entry> me: map.entrySet()) { + for ( final Map.Entry> me : map.entrySet() ) { try { this.insert(me.getKey(), me.getValue()); - } catch (final RowSpaceExceededException e) { + } catch ( final RowSpaceExceededException e ) { Log.logException(e); - } catch (final IOException e) { + } catch ( final IOException e ) { Log.logException(e); } } } /** - * remove all entries from the map; - * possibly removes the backend-file + * remove all entries from the map; possibly removes the backend-file */ + @Override public void clear() { try { this.table.clear(); this.columnames.clear(); - } catch (final IOException e) { + } catch ( final IOException e ) { Log.logException(e); } } /** - * close the backen-file. - * Should be called explicitely to ensure that all data - * waiting in IO write buffers are flushed + * close the backen-file. Should be called explicitely to ensure that all data waiting in IO write buffers + * are flushed */ public void close() { this.table.close(); } /** - * Return a Set of the keys contained in this map. - * This may not be a useful method, if possible use the keys() - * method instead to iterate all keys from the backend-file - * + * Return a Set of the keys contained in this map. This may not be a useful method, if possible use the + * keys() method instead to iterate all keys from the backend-file + * * @return a set view of the keys contained in this map */ + @Override public Set keySet() { final TreeSet set = new TreeSet(this.table.ordering); try { final Iterator i = this.table.keys(true, false); - while (i.hasNext()) set.add(i.next()); - } catch (final IOException e) {} + while ( i.hasNext() ) { + set.add(i.next()); + } + } catch ( final IOException e ) { + } return set; } /** * iterate all keys of the table + * * @return an iterator of byte[] * @throws IOException */ @@ -463,47 +520,43 @@ public class BEncodedHeap implements Map>, Iterable< } /** - * the values() method is not implemented in this class - * because it does not make sense to use such a method for - * file-based data structures. To get a collection view of - * all the entries, just use a entry iterator instead. - * + * the values() method is not implemented in this class because it does not make sense to use such a + * method for file-based data structures. To get a collection view of all the entries, just use a entry + * iterator instead. + * * @return nothing. The method throws always a UnsupportedOperationException */ + @Override public Collection> values() { // this method shall not be used because it is not appropriate for this kind of data throw new UnsupportedOperationException(); } /** - * The abstract method entrySet() from AbstractMap must be implemented, - * but never used because that is not useful for this file-based storage class. - * To prevent the usage, a UnsupportedOperationException is thrown. - * To prevent that the method is used by the methods from AbstractMap, all such - * methods must be overriden in this class. These methods are: - * size, containsValue, containsKey, get, remove, putAll, clear, - * keySet, values, equals, hashCode and toString - * - * Instead of using this method, use the iterator() method to iterate - * all elements in the back-end blob file + * The abstract method entrySet() from AbstractMap must be implemented, but never used because that is not + * useful for this file-based storage class. To prevent the usage, a UnsupportedOperationException is + * thrown. To prevent that the method is used by the methods from AbstractMap, all such methods must be + * overriden in this class. These methods are: size, containsValue, containsKey, get, remove, putAll, + * clear, keySet, values, equals, hashCode and toString Instead of using this method, use the iterator() + * method to iterate all elements in the back-end blob file */ + @Override public Set>> entrySet() { throw new UnsupportedOperationException(); } /** - * iterate all rows of the table. - * This method implements the - * Iterable>> - * interface + * iterate all rows of the table. This method implements the Iterable>> interface */ + @Override public Iterator>> iterator() { final File location = this.table.location(); final int keylen = this.table.keylength(); try { this.table.flushBuffer(); return new EntryIter(location, keylen); - } catch (final IOException e1) { + } catch ( final IOException e1 ) { final ByteOrder order = this.table.ordering(); final int buffermax = this.table.getBuffermax(); this.table.close(); @@ -511,7 +564,7 @@ public class BEncodedHeap implements Map>, Iterable< final Iterator>> iter = new EntryIter(location, keylen); this.table = new Heap(location, keylen, order, buffermax); return iter; - } catch (final IOException e) { + } catch ( final IOException e ) { Log.logSevere("PropertiesTable", e.getMessage(), e); return null; } @@ -519,18 +572,20 @@ public class BEncodedHeap implements Map>, Iterable< } /** - * iterate all rows of the table. this is a static method that expects that the given - * file is not opened by any other application + * iterate all rows of the table. this is a static method that expects that the given file is not opened + * by any other application + * * @param location * @param keylen * @return * @throws IOException */ - public static Iterator>> iterator(final File location, final int keylen) throws IOException { + public static Iterator>> iterator( + final File location, + final int keylen) throws IOException { return new EntryIter(location, keylen); } - /** * a hashcode for the object */ @@ -540,16 +595,15 @@ public class BEncodedHeap implements Map>, Iterable< } /** - * Produce a list of column names from this table - * This method may be useful if the table shall be displayed - * as a table in GUIs. To show the first line of the table, the - * table header, a list of all column names is required. This can - * be generated with this method + * Produce a list of column names from this table This method may be useful if the table shall be + * displayed as a table in GUIs. To show the first line of the table, the table header, a list of all + * column names is required. This can be generated with this method + * * @return a list of column names */ public ArrayList columns() { - if (this.columnames.size() == 0) { - for (final Map.Entry> row: this) { + if ( this.columnames.size() == 0 ) { + for ( final Map.Entry> row : this ) { this.columnames.addAll(row.getValue().keySet()); } } @@ -559,45 +613,50 @@ public class BEncodedHeap implements Map>, Iterable< } public static void main(final String[] args) { - if (args.length == 0) { + if ( args.length == 0 ) { // test the class final File f = new File(new File("maptest").getAbsolutePath()); //System.out.println(f.getAbsolutePath()); //System.out.println(f.getParent()); - if (f.exists()) FileUtils.deletedelete(f); + if ( f.exists() ) { + FileUtils.deletedelete(f); + } try { final BEncodedHeap map = new BEncodedHeap(f, 4); // put some values into the map final Map m = new HashMap(); - m.put("k", "000".getBytes()); map.insert("123".getBytes(), m); - m.put("k", "111".getBytes()); map.insert("456".getBytes(), m); - m.put("k", "222".getBytes()); map.insert("789".getBytes(), m); + m.put("k", "000".getBytes()); + map.insert("123".getBytes(), m); + m.put("k", "111".getBytes()); + map.insert("456".getBytes(), m); + m.put("k", "222".getBytes()); + map.insert("789".getBytes(), m); // iterate over keys Map.Entry> entry; final Iterator>> i = map.iterator(); - while (i.hasNext()) { + while ( i.hasNext() ) { entry = i.next(); System.out.println(ASCII.String(entry.getKey()) + ": " + entry.getValue()); } // clean up map.close(); - } catch (final IOException e) { + } catch ( final IOException e ) { Log.logException(e); - } catch (final RowSpaceExceededException e) { + } catch ( final RowSpaceExceededException e ) { Log.logException(e); } } else { final File f = new File(args[0]); try { - Map.Entry> entry; + Map.Entry> entry; final BEncodedHeap map = new BEncodedHeap(f, 12); final Iterator>> i = map.iterator(); - while (i.hasNext()) { + while ( i.hasNext() ) { entry = i.next(); System.out.println(ASCII.String(entry.getKey()) + ": " + entry.getValue()); } map.close(); - } catch (final IOException e) { + } catch ( final IOException e ) { Log.logException(e); } }