use maven codestyle format, just to reduce checkstyle errors number... Signed-off-by: olivier lamy <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/maven-indexer/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-indexer/commit/8d096a88 Tree: http://git-wip-us.apache.org/repos/asf/maven-indexer/tree/8d096a88 Diff: http://git-wip-us.apache.org/repos/asf/maven-indexer/diff/8d096a88 Branch: refs/heads/master Commit: 8d096a88bc0c74b6315d4166805a2457bff86b33 Parents: 0bbcad1 Author: olivier lamy <[email protected]> Authored: Mon Jul 24 16:51:06 2017 +1000 Committer: olivier lamy <[email protected]> Committed: Mon Jul 24 16:51:06 2017 +1000 ---------------------------------------------------------------------- .../DownloadRemoteIndexerManagerTest.java | 15 +- .../apache/maven/index/reader/ChunkReader.java | 411 +++++----- .../apache/maven/index/reader/ChunkWriter.java | 283 +++---- .../apache/maven/index/reader/IndexReader.java | 438 ++++++----- .../apache/maven/index/reader/IndexWriter.java | 308 ++++---- .../org/apache/maven/index/reader/Record.java | 761 ++++++++++--------- .../maven/index/reader/RecordCompactor.java | 341 +++++---- .../maven/index/reader/RecordExpander.java | 388 +++++----- .../maven/index/reader/ResourceHandler.java | 28 +- .../index/reader/WritableResourceHandler.java | 40 +- 10 files changed, 1586 insertions(+), 1427 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/8d096a88/indexer-core/src/test/java/org/apache/maven/index/updater/DownloadRemoteIndexerManagerTest.java ---------------------------------------------------------------------- diff --git a/indexer-core/src/test/java/org/apache/maven/index/updater/DownloadRemoteIndexerManagerTest.java b/indexer-core/src/test/java/org/apache/maven/index/updater/DownloadRemoteIndexerManagerTest.java index 5dfa7ad..7e0b0c3 100644 --- a/indexer-core/src/test/java/org/apache/maven/index/updater/DownloadRemoteIndexerManagerTest.java +++ b/indexer-core/src/test/java/org/apache/maven/index/updater/DownloadRemoteIndexerManagerTest.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; +import java.nio.file.Files; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; @@ -175,16 +176,18 @@ public class DownloadRemoteIndexerManagerTest assertTrue( lastMod < lastMod2 ); Properties p = new Properties(); - InputStream input = new FileInputStream( indexProperties ); - p.load( input ); - input.close(); + try (InputStream input = Files.newInputStream( indexProperties.toPath() )) + { + p.load( input ); + } p.setProperty( "nexus.index.time", format( new Date() ) ); p.setProperty( "nexus.index.timestamp", format( new Date() ) ); - OutputStream output = new FileOutputStream( indexProperties ); - p.store( output, null ); - output.close(); + try (OutputStream output = Files.newOutputStream( indexProperties.toPath() )) + { + p.store( output, null ); + } } private String format( Date d ) http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/8d096a88/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkReader.java ---------------------------------------------------------------------- diff --git a/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkReader.java b/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkReader.java index a6c75ac..9ce6bfa 100644 --- a/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkReader.java +++ b/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkReader.java @@ -41,219 +41,250 @@ import java.util.zip.GZIPInputStream; public class ChunkReader implements Closeable, Iterable<Map<String, String>> { - private final String chunkName; - - private final DataInputStream dataInputStream; - - private final int version; - - private final Date timestamp; - - public ChunkReader(final String chunkName, final InputStream inputStream) throws IOException - { - this.chunkName = chunkName.trim(); - this.dataInputStream = new DataInputStream(new GZIPInputStream(inputStream, 2 * 1024)); - this.version = ((int) dataInputStream.readByte()) & 0xff; - this.timestamp = new Date(dataInputStream.readLong()); - } - - /** - * Returns the chunk name. - */ - public String getName() { - return chunkName; - } - - /** - * Returns index version. All releases so far always returned {@code 1}. - */ - public int getVersion() { - return version; - } - - /** - * Returns the index timestamp of last update of the index. - */ - public Date getTimestamp() { - return timestamp; - } - - /** - * Returns the {@link Record} iterator. - */ - public Iterator<Map<String, String>> iterator() { - try { - return new IndexIterator(dataInputStream); - } - catch (IOException e) { - throw new RuntimeException("error", e); - } - } - - /** - * Closes this reader and it's underlying input. - */ - public void close() throws IOException { - dataInputStream.close(); - } - - /** - * Low memory footprint index iterator that incrementally parses the underlying stream. - */ - private static class IndexIterator - implements Iterator<Map<String, String>> - { + private final String chunkName; + private final DataInputStream dataInputStream; - private Map<String, String> nextRecord; + private final int version; - public IndexIterator(final DataInputStream dataInputStream) throws IOException { - this.dataInputStream = dataInputStream; - this.nextRecord = nextRecord(); - } + private final Date timestamp; - public boolean hasNext() { - return nextRecord != null; + public ChunkReader( final String chunkName, final InputStream inputStream ) + throws IOException + { + this.chunkName = chunkName.trim(); + this.dataInputStream = new DataInputStream( new GZIPInputStream( inputStream, 2 * 1024 ) ); + this.version = ( (int) dataInputStream.readByte() ) & 0xff; + this.timestamp = new Date( dataInputStream.readLong() ); } - public Map<String, String> next() { - if (nextRecord == null) { - throw new NoSuchElementException("chunk depleted"); - } - Map<String, String> result = nextRecord; - nextRecord = nextRecord(); - return result; + /** + * Returns the chunk name. + */ + public String getName() + { + return chunkName; } - public void remove() { - throw new UnsupportedOperationException("remove"); + /** + * Returns index version. All releases so far always returned {@code 1}. + */ + public int getVersion() + { + return version; } - private Map<String, String> nextRecord() { - try { - return readRecord(dataInputStream); - } - catch (IOException e) { - throw new RuntimeException("read error", e); - } - } - } - - /** - * Reads and returns next record from the underlying stream, or {@code null} if no more records. - */ - private static Map<String, String> readRecord(final DataInput dataInput) - throws IOException - { - int fieldCount; - try { - fieldCount = dataInput.readInt(); - } - catch (EOFException ex) { - return null; // no more documents + /** + * Returns the index timestamp of last update of the index. + */ + public Date getTimestamp() + { + return timestamp; } - Map<String, String> recordMap = new HashMap<String, String>(); - for (int i = 0; i < fieldCount; i++) { - readField(recordMap, dataInput); + /** + * Returns the {@link Record} iterator. + */ + public Iterator<Map<String, String>> iterator() + { + try + { + return new IndexIterator( dataInputStream ); + } + catch ( IOException e ) + { + throw new RuntimeException( "error", e ); + } } - return recordMap; - } - - private static void readField(final Map<String, String> record, final DataInput dataInput) - throws IOException - { - dataInput.readByte(); // flags: neglect them - String name = dataInput.readUTF(); - String value = readUTF(dataInput); - record.put(name, value); - } - - private static String readUTF(final DataInput dataInput) - throws IOException - { - int utflen = dataInput.readInt(); - - byte[] bytearr; - char[] chararr; - - try { - bytearr = new byte[utflen]; - chararr = new char[utflen]; - } - catch (OutOfMemoryError e) { - IOException ioex = new IOException("Index data content is corrupt"); - ioex.initCause(e); - throw ioex; + + /** + * Closes this reader and it's underlying input. + */ + public void close() + throws IOException + { + dataInputStream.close(); } - int c, char2, char3; - int count = 0; - int chararr_count = 0; + /** + * Low memory footprint index iterator that incrementally parses the underlying stream. + */ + private static class IndexIterator + implements Iterator<Map<String, String>> + { + private final DataInputStream dataInputStream; + + private Map<String, String> nextRecord; + + public IndexIterator( final DataInputStream dataInputStream ) + throws IOException + { + this.dataInputStream = dataInputStream; + this.nextRecord = nextRecord(); + } + + public boolean hasNext() + { + return nextRecord != null; + } + + public Map<String, String> next() + { + if ( nextRecord == null ) + { + throw new NoSuchElementException( "chunk depleted" ); + } + Map<String, String> result = nextRecord; + nextRecord = nextRecord(); + return result; + } + + public void remove() + { + throw new UnsupportedOperationException( "remove" ); + } + + private Map<String, String> nextRecord() + { + try + { + return readRecord( dataInputStream ); + } + catch ( IOException e ) + { + throw new RuntimeException( "read error", e ); + } + } + } - dataInput.readFully(bytearr, 0, utflen); + /** + * Reads and returns next record from the underlying stream, or {@code null} if no more records. + */ + private static Map<String, String> readRecord( final DataInput dataInput ) + throws IOException + { + int fieldCount; + try + { + fieldCount = dataInput.readInt(); + } + catch ( EOFException ex ) + { + return null; // no more documents + } + + Map<String, String> recordMap = new HashMap<String, String>(); + for ( int i = 0; i < fieldCount; i++ ) + { + readField( recordMap, dataInput ); + } + return recordMap; + } - while (count < utflen) { - c = bytearr[count] & 0xff; - if (c > 127) { - break; - } - count++; - chararr[chararr_count++] = (char) c; + private static void readField( final Map<String, String> record, final DataInput dataInput ) + throws IOException + { + dataInput.readByte(); // flags: neglect them + String name = dataInput.readUTF(); + String value = readUTF( dataInput ); + record.put( name, value ); } - while (count < utflen) { - c = bytearr[count] & 0xff; - switch (c >> 4) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: + private static String readUTF( final DataInput dataInput ) + throws IOException + { + int utflen = dataInput.readInt(); + + byte[] bytearr; + char[] chararr; + + try + { + bytearr = new byte[utflen]; + chararr = new char[utflen]; + } + catch ( OutOfMemoryError e ) + { + IOException ioex = new IOException( "Index data content is corrupt" ); + ioex.initCause( e ); + throw ioex; + } + + int c, char2, char3; + int count = 0; + int chararr_count = 0; + + dataInput.readFully( bytearr, 0, utflen ); + + while ( count < utflen ) + { + c = bytearr[count] & 0xff; + if ( c > 127 ) + { + break; + } + count++; + chararr[chararr_count++] = (char) c; + } + + while ( count < utflen ) + { + c = bytearr[count] & 0xff; + switch ( c >> 4 ) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: /* 0xxxxxxx */ - count++; - chararr[chararr_count++] = (char) c; - break; + count++; + chararr[chararr_count++] = (char) c; + break; - case 12: - case 13: + case 12: + case 13: /* 110x xxxx 10xx xxxx */ - count += 2; - if (count > utflen) { - throw new UTFDataFormatException("malformed input: partial character at end"); - } - char2 = bytearr[count - 1]; - if ((char2 & 0xC0) != 0x80) { - throw new UTFDataFormatException("malformed input around byte " + count); - } - chararr[chararr_count++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F)); - break; - - case 14: + count += 2; + if ( count > utflen ) + { + throw new UTFDataFormatException( "malformed input: partial character at end" ); + } + char2 = bytearr[count - 1]; + if ( ( char2 & 0xC0 ) != 0x80 ) + { + throw new UTFDataFormatException( "malformed input around byte " + count ); + } + chararr[chararr_count++] = (char) ( ( ( c & 0x1F ) << 6 ) | ( char2 & 0x3F ) ); + break; + + case 14: /* 1110 xxxx 10xx xxxx 10xx xxxx */ - count += 3; - if (count > utflen) { - throw new UTFDataFormatException("malformed input: partial character at end"); - } - char2 = bytearr[count - 2]; - char3 = bytearr[count - 1]; - if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) { - throw new UTFDataFormatException("malformed input around byte " + (count - 1)); - } - chararr[chararr_count++] = - (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F)); - break; - - default: + count += 3; + if ( count > utflen ) + { + throw new UTFDataFormatException( "malformed input: partial character at end" ); + } + char2 = bytearr[count - 2]; + char3 = bytearr[count - 1]; + if ( ( ( char2 & 0xC0 ) != 0x80 ) || ( ( char3 & 0xC0 ) != 0x80 ) ) + { + throw new UTFDataFormatException( "malformed input around byte " + ( count - 1 ) ); + } + chararr[chararr_count++] = + (char) ( ( ( c & 0x0F ) << 12 ) | ( ( char2 & 0x3F ) << 6 ) | ( char3 & 0x3F ) ); + break; + + default: /* 10xx xxxx, 1111 xxxx */ - throw new UTFDataFormatException("malformed input around byte " + count); - } - } + throw new UTFDataFormatException( "malformed input around byte " + count ); + } + } - // The number of chars produced may be less than utflen - return new String(chararr, 0, chararr_count); - } + // The number of chars produced may be less than utflen + return new String( chararr, 0, chararr_count ); + } } http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/8d096a88/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkWriter.java ---------------------------------------------------------------------- diff --git a/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkWriter.java b/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkWriter.java index 24e4701..7d1275c 100644 --- a/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkWriter.java +++ b/indexer-reader/src/main/java/org/apache/maven/index/reader/ChunkWriter.java @@ -37,141 +37,160 @@ import java.util.zip.GZIPOutputStream; public class ChunkWriter implements Closeable { - private static final int F_INDEXED = 1; - - private static final int F_TOKENIZED = 2; - - private static final int F_STORED = 4; - - private final String chunkName; - - private final DataOutputStream dataOutputStream; - - private final int version; - - private final Date timestamp; - - public ChunkWriter(final String chunkName, final OutputStream outputStream, final int version, final Date timestamp) - throws IOException - { - this.chunkName = chunkName.trim(); - this.dataOutputStream = new DataOutputStream(new GZIPOutputStream(outputStream, 2 * 1024)); - this.version = version; - this.timestamp = timestamp; - - dataOutputStream.writeByte(version); - dataOutputStream.writeLong(timestamp == null ? -1 : timestamp.getTime()); - } - - /** - * Returns the chunk name. - */ - public String getName() { - return chunkName; - } - - /** - * Returns index version. All releases so far always returned {@code 1}. - */ - public int getVersion() { - return version; - } - - /** - * Returns the index timestamp of last update of the index. - */ - public Date getTimestamp() { - return timestamp; - } - - /** - * Writes out the record iterator and returns the written record count. - */ - public int writeChunk(final Iterator<Map<String, String>> iterator) throws IOException { - int written = 0; - while (iterator.hasNext()) { - writeRecord(iterator.next(), dataOutputStream); - written++; + private static final int F_INDEXED = 1; + + private static final int F_TOKENIZED = 2; + + private static final int F_STORED = 4; + + private final String chunkName; + + private final DataOutputStream dataOutputStream; + + private final int version; + + private final Date timestamp; + + public ChunkWriter( final String chunkName, final OutputStream outputStream, final int version, + final Date timestamp ) + throws IOException + { + this.chunkName = chunkName.trim(); + this.dataOutputStream = new DataOutputStream( new GZIPOutputStream( outputStream, 2 * 1024 ) ); + this.version = version; + this.timestamp = timestamp; + + dataOutputStream.writeByte( version ); + dataOutputStream.writeLong( timestamp == null ? -1 : timestamp.getTime() ); + } + + /** + * Returns the chunk name. + */ + public String getName() + { + return chunkName; } - return written; - } - - /** - * Closes this reader and it's underlying input. - */ - public void close() throws IOException { - dataOutputStream.close(); - } - - private static void writeRecord(final Map<String, String> record, final DataOutput dataOutput) - throws IOException - { - dataOutput.writeInt(record.size()); - for (Map.Entry<String, String> entry : record.entrySet()) { - writeField(entry.getKey(), entry.getValue(), dataOutput); + + /** + * Returns index version. All releases so far always returned {@code 1}. + */ + public int getVersion() + { + return version; + } + + /** + * Returns the index timestamp of last update of the index. + */ + public Date getTimestamp() + { + return timestamp; + } + + /** + * Writes out the record iterator and returns the written record count. + */ + public int writeChunk( final Iterator<Map<String, String>> iterator ) + throws IOException + { + int written = 0; + while ( iterator.hasNext() ) + { + writeRecord( iterator.next(), dataOutputStream ); + written++; + } + return written; } - } - - private static void writeField(final String fieldName, final String fieldValue, final DataOutput dataOutput) - throws IOException - { - boolean isIndexed = !(fieldName.equals("i") || fieldName.equals("m")); - boolean isTokenized = !(fieldName.equals("i") - || fieldName.equals("m") - || fieldName.equals("1") - || fieldName.equals("px")); - int flags = (isIndexed ? F_INDEXED : 0) + (isTokenized ? F_TOKENIZED : 0) + F_STORED; - dataOutput.writeByte(flags); - dataOutput.writeUTF(fieldName); - writeUTF(fieldValue, dataOutput); - } - - private static void writeUTF(final String str, final DataOutput dataOutput) - throws IOException - { - int strlen = str.length(); - int utflen = 0; - int c; - // use charAt instead of copying String to char array - for (int i = 0; i < strlen; i++) { - c = str.charAt(i); - if ((c >= 0x0001) && (c <= 0x007F)) { - utflen++; - } - else if (c > 0x07FF) { - utflen += 3; - } - else { - utflen += 2; - } + + /** + * Closes this reader and it's underlying input. + */ + public void close() + throws IOException + { + dataOutputStream.close(); } - dataOutput.writeInt(utflen); - byte[] bytearr = new byte[utflen]; - int count = 0; - int i = 0; - for (; i < strlen; i++) { - c = str.charAt(i); - if (!((c >= 0x0001) && (c <= 0x007F))) { - break; - } - bytearr[count++] = (byte) c; + + private static void writeRecord( final Map<String, String> record, final DataOutput dataOutput ) + throws IOException + { + dataOutput.writeInt( record.size() ); + for ( Map.Entry<String, String> entry : record.entrySet() ) + { + writeField( entry.getKey(), entry.getValue(), dataOutput ); + } } - for (; i < strlen; i++) { - c = str.charAt(i); - if ((c >= 0x0001) && (c <= 0x007F)) { - bytearr[count++] = (byte) c; - - } - else if (c > 0x07FF) { - bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F)); - bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F)); - bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F)); - } - else { - bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F)); - bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F)); - } + + private static void writeField( final String fieldName, final String fieldValue, final DataOutput dataOutput ) + throws IOException + { + boolean isIndexed = !( fieldName.equals( "i" ) || fieldName.equals( "m" ) ); + boolean isTokenized = + !( fieldName.equals( "i" ) || fieldName.equals( "m" ) || fieldName.equals( "1" ) || fieldName.equals( + "px" ) ); + int flags = ( isIndexed ? F_INDEXED : 0 ) + ( isTokenized ? F_TOKENIZED : 0 ) + F_STORED; + dataOutput.writeByte( flags ); + dataOutput.writeUTF( fieldName ); + writeUTF( fieldValue, dataOutput ); + } + + private static void writeUTF( final String str, final DataOutput dataOutput ) + throws IOException + { + int strlen = str.length(); + int utflen = 0; + int c; + // use charAt instead of copying String to char array + for ( int i = 0; i < strlen; i++ ) + { + c = str.charAt( i ); + if ( ( c >= 0x0001 ) && ( c <= 0x007F ) ) + { + utflen++; + } + else if ( c > 0x07FF ) + { + utflen += 3; + } + else + { + utflen += 2; + } + } + dataOutput.writeInt( utflen ); + byte[] bytearr = new byte[utflen]; + int count = 0; + int i = 0; + for ( ; i < strlen; i++ ) + { + c = str.charAt( i ); + if ( !( ( c >= 0x0001 ) && ( c <= 0x007F ) ) ) + { + break; + } + bytearr[count++] = (byte) c; + } + for ( ; i < strlen; i++ ) + { + c = str.charAt( i ); + if ( ( c >= 0x0001 ) && ( c <= 0x007F ) ) + { + bytearr[count++] = (byte) c; + + } + else if ( c > 0x07FF ) + { + bytearr[count++] = (byte) ( 0xE0 | ( ( c >> 12 ) & 0x0F ) ); + bytearr[count++] = (byte) ( 0x80 | ( ( c >> 6 ) & 0x3F ) ); + bytearr[count++] = (byte) ( 0x80 | ( ( c >> 0 ) & 0x3F ) ); + } + else + { + bytearr[count++] = (byte) ( 0xC0 | ( ( c >> 6 ) & 0x1F ) ); + bytearr[count++] = (byte) ( 0x80 | ( ( c >> 0 ) & 0x3F ) ); + } + } + dataOutput.write( bytearr, 0, utflen ); } - dataOutput.write(bytearr, 0, utflen); - } } http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/8d096a88/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexReader.java ---------------------------------------------------------------------- diff --git a/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexReader.java b/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexReader.java index 1f75864..8f3ee2a 100644 --- a/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexReader.java +++ b/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexReader.java @@ -19,6 +19,8 @@ package org.apache.maven.index.reader; * under the License. */ +import org.apache.maven.index.reader.ResourceHandler.Resource; + import java.io.Closeable; import java.io.IOException; import java.text.ParseException; @@ -29,8 +31,6 @@ import java.util.Iterator; import java.util.List; import java.util.Properties; -import org.apache.maven.index.reader.ResourceHandler.Resource; - import static org.apache.maven.index.reader.Utils.loadProperties; import static org.apache.maven.index.reader.Utils.storeProperties; @@ -43,230 +43,272 @@ import static org.apache.maven.index.reader.Utils.storeProperties; public class IndexReader implements Iterable<ChunkReader>, Closeable { - private final WritableResourceHandler local; + private final WritableResourceHandler local; - private final ResourceHandler remote; + private final ResourceHandler remote; - private final Properties localIndexProperties; + private final Properties localIndexProperties; - private final Properties remoteIndexProperties; + private final Properties remoteIndexProperties; - private final String indexId; + private final String indexId; - private final Date publishedTimestamp; + private final Date publishedTimestamp; - private final boolean incremental; + private final boolean incremental; - private final List<String> chunkNames; + private final List<String> chunkNames; - public IndexReader(final WritableResourceHandler local, final ResourceHandler remote) throws IOException { - if (remote == null) { - throw new NullPointerException("remote resource handler null"); - } - this.local = local; - this.remote = remote; - remoteIndexProperties = loadProperties(remote.locate(Utils.INDEX_FILE_PREFIX + ".properties")); - if (remoteIndexProperties == null) { - throw new IllegalArgumentException("Non-existent remote index"); - } - try { - if (local != null) { - Properties localProperties = loadProperties(local.locate(Utils.INDEX_FILE_PREFIX + ".properties")); - if (localProperties != null) { - this.localIndexProperties = localProperties; - String remoteIndexId = remoteIndexProperties.getProperty("nexus.index.id"); - String localIndexId = localIndexProperties.getProperty("nexus.index.id"); - if (remoteIndexId == null || localIndexId == null || !remoteIndexId.equals(localIndexId)) { - throw new IllegalArgumentException( - "local and remote index IDs does not match or is null: " + localIndexId + ", " + - remoteIndexId); - } - this.indexId = localIndexId; - this.incremental = canRetrieveAllChunks(); + public IndexReader( final WritableResourceHandler local, final ResourceHandler remote ) + throws IOException + { + if ( remote == null ) + { + throw new NullPointerException( "remote resource handler null" ); + } + this.local = local; + this.remote = remote; + remoteIndexProperties = loadProperties( remote.locate( Utils.INDEX_FILE_PREFIX + ".properties" ) ); + if ( remoteIndexProperties == null ) + { + throw new IllegalArgumentException( "Non-existent remote index" ); + } + try + { + if ( local != null ) + { + Properties localProperties = loadProperties( local.locate( Utils.INDEX_FILE_PREFIX + ".properties" ) ); + if ( localProperties != null ) + { + this.localIndexProperties = localProperties; + String remoteIndexId = remoteIndexProperties.getProperty( "nexus.index.id" ); + String localIndexId = localIndexProperties.getProperty( "nexus.index.id" ); + if ( remoteIndexId == null || localIndexId == null || !remoteIndexId.equals( localIndexId ) ) + { + throw new IllegalArgumentException( + "local and remote index IDs does not match or is null: " + localIndexId + ", " + + remoteIndexId ); + } + this.indexId = localIndexId; + this.incremental = canRetrieveAllChunks(); + } + else + { + localIndexProperties = null; + this.indexId = remoteIndexProperties.getProperty( "nexus.index.id" ); + this.incremental = false; + } + } + else + { + localIndexProperties = null; + this.indexId = remoteIndexProperties.getProperty( "nexus.index.id" ); + this.incremental = false; + } + this.publishedTimestamp = + Utils.INDEX_DATE_FORMAT.parse( remoteIndexProperties.getProperty( "nexus.index.timestamp" ) ); + this.chunkNames = calculateChunkNames(); } - else { - localIndexProperties = null; - this.indexId = remoteIndexProperties.getProperty("nexus.index.id"); - this.incremental = false; + catch ( ParseException e ) + { + IOException ex = new IOException( "Index properties corrupted" ); + ex.initCause( e ); + throw ex; } - } - else { - localIndexProperties = null; - this.indexId = remoteIndexProperties.getProperty("nexus.index.id"); - this.incremental = false; - } - this.publishedTimestamp = Utils.INDEX_DATE_FORMAT.parse(remoteIndexProperties.getProperty("nexus.index.timestamp")); - this.chunkNames = calculateChunkNames(); } - catch (ParseException e) { - IOException ex = new IOException("Index properties corrupted"); - ex.initCause(e); - throw ex; + + /** + * Returns the index context ID that published index has set. Usually it is equal to "repository ID" used in {@link + * Record.Type#DESCRIPTOR} but does not have to be. + */ + public String getIndexId() + { + return indexId; + } + + /** + * Returns the {@link Date} when remote index was last published. + */ + public Date getPublishedTimestamp() + { + return publishedTimestamp; } - } - - /** - * Returns the index context ID that published index has set. Usually it is equal to "repository ID" used in {@link - * Record.Type#DESCRIPTOR} but does not have to be. - */ - public String getIndexId() { - return indexId; - } - - /** - * Returns the {@link Date} when remote index was last published. - */ - public Date getPublishedTimestamp() { - return publishedTimestamp; - } - - /** - * Returns {@code true} if incremental update is about to happen. If incremental update, the {@link #iterator()} will - * return only the diff from the last update. - */ - public boolean isIncremental() { - return incremental; - } - - /** - * Returns unmodifiable list of actual chunks that needs to be pulled from remote {@link ResourceHandler}. Those are - * incremental chunks or the big main file, depending on result of {@link #isIncremental()}. Empty list means local - * index is up to date, and {@link #iterator()} will return empty iterator. - */ - public List<String> getChunkNames() { - return chunkNames; - } - - /** - * Closes the underlying {@link ResourceHandler}s. In case of incremental update use, it also assumes that user - * consumed all the iterator and integrated it, hence, it will update the {@link WritableResourceHandler} contents to - * prepare it for future incremental update. If this is not desired (ie. due to aborted update), then this method - * should NOT be invoked, but rather the {@link ResourceHandler}s that caller provided in constructor of - * this class should be closed manually. - */ - public void close() throws IOException { - remote.close(); - if (local != null) { - try { - syncLocalWithRemote(); - } - finally { - local.close(); - } + + /** + * Returns {@code true} if incremental update is about to happen. If incremental update, the {@link #iterator()} will + * return only the diff from the last update. + */ + public boolean isIncremental() + { + return incremental; } - } - - /** - * Returns an {@link Iterator} of {@link ChunkReader}s, that if read in sequence, provide all the (incremental) - * updates from the index. It is caller responsibility to either consume fully this iterator, or to close current - * {@link ChunkReader} if aborting. - */ - public Iterator<ChunkReader> iterator() { - return new ChunkReaderIterator(remote, chunkNames.iterator()); - } - - /** - * Stores the remote index properties into local index properties, preparing local {@link WritableResourceHandler} - * for future incremental updates. - */ - private void syncLocalWithRemote() throws IOException { - storeProperties(local.locate(Utils.INDEX_FILE_PREFIX + ".properties"), remoteIndexProperties); - } - - /** - * Calculates the chunk names that needs to be fetched. - */ - private List<String> calculateChunkNames() { - if (incremental) { - ArrayList<String> chunkNames = new ArrayList<>(); - int maxCounter = Integer.parseInt(remoteIndexProperties.getProperty("nexus.index.last-incremental")); - int currentCounter = Integer.parseInt(localIndexProperties.getProperty("nexus.index.last-incremental")); - currentCounter++; - while (currentCounter <= maxCounter) { - chunkNames.add(Utils.INDEX_FILE_PREFIX + "." + currentCounter++ + ".gz"); - } - return Collections.unmodifiableList(chunkNames); + + /** + * Returns unmodifiable list of actual chunks that needs to be pulled from remote {@link ResourceHandler}. Those are + * incremental chunks or the big main file, depending on result of {@link #isIncremental()}. Empty list means local + * index is up to date, and {@link #iterator()} will return empty iterator. + */ + public List<String> getChunkNames() + { + return chunkNames; + } + + /** + * Closes the underlying {@link ResourceHandler}s. In case of incremental update use, it also assumes that user + * consumed all the iterator and integrated it, hence, it will update the {@link WritableResourceHandler} contents to + * prepare it for future incremental update. If this is not desired (ie. due to aborted update), then this method + * should NOT be invoked, but rather the {@link ResourceHandler}s that caller provided in constructor of + * this class should be closed manually. + */ + public void close() + throws IOException + { + remote.close(); + if ( local != null ) + { + try + { + syncLocalWithRemote(); + } + finally + { + local.close(); + } + } } - else { - return Collections.singletonList(Utils.INDEX_FILE_PREFIX + ".gz"); + + /** + * Returns an {@link Iterator} of {@link ChunkReader}s, that if read in sequence, provide all the (incremental) + * updates from the index. It is caller responsibility to either consume fully this iterator, or to close current + * {@link ChunkReader} if aborting. + */ + public Iterator<ChunkReader> iterator() + { + return new ChunkReaderIterator( remote, chunkNames.iterator() ); } - } - - /** - * Verifies incremental update is possible, as all the diff chunks we need are still enlisted in remote properties. - */ - private boolean canRetrieveAllChunks() - { - String localChainId = localIndexProperties.getProperty("nexus.index.chain-id"); - String remoteChainId = remoteIndexProperties.getProperty("nexus.index.chain-id"); - - // If no chain id, or not the same, do full update - if (localChainId == null || remoteChainId == null || !localChainId.equals(remoteChainId)) { - return false; + + /** + * Stores the remote index properties into local index properties, preparing local {@link WritableResourceHandler} + * for future incremental updates. + */ + private void syncLocalWithRemote() + throws IOException + { + storeProperties( local.locate( Utils.INDEX_FILE_PREFIX + ".properties" ), remoteIndexProperties ); } - try { - int localLastIncremental = Integer.parseInt(localIndexProperties.getProperty("nexus.index.last-incremental")); - String currentLocalCounter = String.valueOf(localLastIncremental); - String nextLocalCounter = String.valueOf(localLastIncremental + 1); - // check remote props for existence of current or next chunk after local - for (Object key : remoteIndexProperties.keySet()) { - String sKey = (String) key; - if (sKey.startsWith("nexus.index.incremental-")) { - String value = remoteIndexProperties.getProperty(sKey); - if (currentLocalCounter.equals(value) || nextLocalCounter.equals(value)) { - return true; - } + /** + * Calculates the chunk names that needs to be fetched. + */ + private List<String> calculateChunkNames() + { + if ( incremental ) + { + ArrayList<String> chunkNames = new ArrayList<>(); + int maxCounter = Integer.parseInt( remoteIndexProperties.getProperty( "nexus.index.last-incremental" ) ); + int currentCounter = Integer.parseInt( localIndexProperties.getProperty( "nexus.index.last-incremental" ) ); + currentCounter++; + while ( currentCounter <= maxCounter ) + { + chunkNames.add( Utils.INDEX_FILE_PREFIX + "." + currentCounter++ + ".gz" ); + } + return Collections.unmodifiableList( chunkNames ); + } + else + { + return Collections.singletonList( Utils.INDEX_FILE_PREFIX + ".gz" ); } - } } - catch (NumberFormatException e) { - // fall through + + /** + * Verifies incremental update is possible, as all the diff chunks we need are still enlisted in remote properties. + */ + private boolean canRetrieveAllChunks() + { + String localChainId = localIndexProperties.getProperty( "nexus.index.chain-id" ); + String remoteChainId = remoteIndexProperties.getProperty( "nexus.index.chain-id" ); + + // If no chain id, or not the same, do full update + if ( localChainId == null || remoteChainId == null || !localChainId.equals( remoteChainId ) ) + { + return false; + } + + try + { + int localLastIncremental = + Integer.parseInt( localIndexProperties.getProperty( "nexus.index.last-incremental" ) ); + String currentLocalCounter = String.valueOf( localLastIncremental ); + String nextLocalCounter = String.valueOf( localLastIncremental + 1 ); + // check remote props for existence of current or next chunk after local + for ( Object key : remoteIndexProperties.keySet() ) + { + String sKey = (String) key; + if ( sKey.startsWith( "nexus.index.incremental-" ) ) + { + String value = remoteIndexProperties.getProperty( sKey ); + if ( currentLocalCounter.equals( value ) || nextLocalCounter.equals( value ) ) + { + return true; + } + } + } + } + catch ( NumberFormatException e ) + { + // fall through + } + return false; } - return false; - } - /** - * Internal iterator implementation that lazily opens and closes the returned {@link ChunkReader}s as this iterator - * is being consumed. - */ - private static class ChunkReaderIterator - implements Iterator<ChunkReader> - { - private final ResourceHandler resourceHandler; + /** + * Internal iterator implementation that lazily opens and closes the returned {@link ChunkReader}s as this iterator + * is being consumed. + */ + private static class ChunkReaderIterator + implements Iterator<ChunkReader> + { + private final ResourceHandler resourceHandler; - private final Iterator<String> chunkNamesIterator; + private final Iterator<String> chunkNamesIterator; - private Resource currentResource; + private Resource currentResource; - private ChunkReader currentChunkReader; + private ChunkReader currentChunkReader; - private ChunkReaderIterator(final ResourceHandler resourceHandler, final Iterator<String> chunkNamesIterator) { - this.resourceHandler = resourceHandler; - this.chunkNamesIterator = chunkNamesIterator; - } + private ChunkReaderIterator( final ResourceHandler resourceHandler, final Iterator<String> chunkNamesIterator ) + { + this.resourceHandler = resourceHandler; + this.chunkNamesIterator = chunkNamesIterator; + } - public boolean hasNext() { - return chunkNamesIterator.hasNext(); - } + public boolean hasNext() + { + return chunkNamesIterator.hasNext(); + } - public ChunkReader next() { - String chunkName = chunkNamesIterator.next(); - try { - if (currentChunkReader != null) { - currentChunkReader.close(); + public ChunkReader next() + { + String chunkName = chunkNamesIterator.next(); + try + { + if ( currentChunkReader != null ) + { + currentChunkReader.close(); + } + currentResource = resourceHandler.locate( chunkName ); + currentChunkReader = new ChunkReader( chunkName, currentResource.read() ); + return currentChunkReader; + } + catch ( IOException e ) + { + throw new RuntimeException( "IO problem while switching chunk readers", e ); + } } - currentResource = resourceHandler.locate(chunkName); - currentChunkReader = new ChunkReader(chunkName, currentResource.read()); - return currentChunkReader; - } - catch (IOException e) { - throw new RuntimeException("IO problem while switching chunk readers", e); - } - } - public void remove() { - throw new UnsupportedOperationException("remove"); + public void remove() + { + throw new UnsupportedOperationException( "remove" ); + } } - } } http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/8d096a88/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexWriter.java ---------------------------------------------------------------------- diff --git a/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexWriter.java b/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexWriter.java index 68d4abb..e997b67 100644 --- a/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexWriter.java +++ b/indexer-reader/src/main/java/org/apache/maven/index/reader/IndexWriter.java @@ -19,6 +19,8 @@ package org.apache.maven.index.reader; * under the License. */ +import org.apache.maven.index.reader.WritableResourceHandler.WritableResource; + import java.io.Closeable; import java.io.IOException; import java.text.ParseException; @@ -28,8 +30,6 @@ import java.util.Map; import java.util.Properties; import java.util.UUID; -import org.apache.maven.index.reader.WritableResourceHandler.WritableResource; - import static org.apache.maven.index.reader.Utils.loadProperties; import static org.apache.maven.index.reader.Utils.storeProperties; @@ -44,153 +44,177 @@ import static org.apache.maven.index.reader.Utils.storeProperties; public class IndexWriter implements Closeable { - private static final int INDEX_V1 = 1; - - private final WritableResourceHandler local; - - private final Properties localIndexProperties; - - private final boolean incremental; - - private final String nextChunkCounter; - - private final String nextChunkName; - - public IndexWriter(final WritableResourceHandler local, final String indexId, final boolean incrementalSupported) - throws IOException - { - if (local == null) { - throw new NullPointerException("local resource handler null"); - } - if (indexId == null) { - throw new NullPointerException("indexId null"); + private static final int INDEX_V1 = 1; + + private final WritableResourceHandler local; + + private final Properties localIndexProperties; + + private final boolean incremental; + + private final String nextChunkCounter; + + private final String nextChunkName; + + public IndexWriter( final WritableResourceHandler local, final String indexId, final boolean incrementalSupported ) + throws IOException + { + if ( local == null ) + { + throw new NullPointerException( "local resource handler null" ); + } + if ( indexId == null ) + { + throw new NullPointerException( "indexId null" ); + } + this.local = local; + Properties indexProperties = loadProperties( local.locate( Utils.INDEX_FILE_PREFIX + ".properties" ) ); + if ( incrementalSupported && indexProperties != null ) + { + this.localIndexProperties = indexProperties; + // existing index, this is incremental publish, and we will add new chunk + String localIndexId = localIndexProperties.getProperty( "nexus.index.id" ); + if ( localIndexId == null || !localIndexId.equals( indexId ) ) + { + throw new IllegalArgumentException( + "index already exists and indexId mismatch or unreadable: " + localIndexId + ", " + indexId ); + } + this.incremental = true; + this.nextChunkCounter = calculateNextChunkCounter(); + this.nextChunkName = Utils.INDEX_FILE_PREFIX + "." + nextChunkCounter + ".gz"; + } + else + { + // non-existing index, create published index from scratch + this.localIndexProperties = new Properties(); + this.localIndexProperties.setProperty( "nexus.index.id", indexId ); + this.localIndexProperties.setProperty( "nexus.index.chain-id", UUID.randomUUID().toString() ); + this.incremental = false; + this.nextChunkCounter = null; + this.nextChunkName = Utils.INDEX_FILE_PREFIX + ".gz"; + } } - this.local = local; - Properties indexProperties = loadProperties(local.locate(Utils.INDEX_FILE_PREFIX + ".properties")); - if (incrementalSupported && indexProperties != null) { - this.localIndexProperties = indexProperties; - // existing index, this is incremental publish, and we will add new chunk - String localIndexId = localIndexProperties.getProperty("nexus.index.id"); - if (localIndexId == null || !localIndexId.equals(indexId)) { - throw new IllegalArgumentException( - "index already exists and indexId mismatch or unreadable: " + localIndexId + ", " + - indexId); - } - this.incremental = true; - this.nextChunkCounter = calculateNextChunkCounter(); - this.nextChunkName = Utils.INDEX_FILE_PREFIX + "." + nextChunkCounter + ".gz"; - } - else { - // non-existing index, create published index from scratch - this.localIndexProperties = new Properties(); - this.localIndexProperties.setProperty("nexus.index.id", indexId); - this.localIndexProperties.setProperty("nexus.index.chain-id", UUID.randomUUID().toString()); - this.incremental = false; - this.nextChunkCounter = null; - this.nextChunkName = Utils.INDEX_FILE_PREFIX + ".gz"; - } - } - - /** - * Returns the index context ID that published index has set. - */ - public String getIndexId() { - return localIndexProperties.getProperty("nexus.index.id"); - } - - /** - * Returns the {@link Date} when index was last published or {@code null} if this is first publishing. In other - * words,returns {@code null} when {@link #isIncremental()} returns {@code false}. After this writer is closed, the - * return value is updated to "now" (in {@link #close() method}. - */ - public Date getPublishedTimestamp() { - try { - String timestamp = localIndexProperties.getProperty("nexus.index.timestamp"); - if (timestamp != null) { - return Utils.INDEX_DATE_FORMAT.parse(timestamp); - } - return null; + + /** + * Returns the index context ID that published index has set. + */ + public String getIndexId() + { + return localIndexProperties.getProperty( "nexus.index.id" ); } - catch (ParseException e) { - throw new RuntimeException("Corrupt date", e); + + /** + * Returns the {@link Date} when index was last published or {@code null} if this is first publishing. In other + * words,returns {@code null} when {@link #isIncremental()} returns {@code false}. After this writer is closed, the + * return value is updated to "now" (in {@link #close() method}. + */ + public Date getPublishedTimestamp() + { + try + { + String timestamp = localIndexProperties.getProperty( "nexus.index.timestamp" ); + if ( timestamp != null ) + { + return Utils.INDEX_DATE_FORMAT.parse( timestamp ); + } + return null; + } + catch ( ParseException e ) + { + throw new RuntimeException( "Corrupt date", e ); + } } - } - - /** - * Returns {@code true} if incremental publish is about to happen. - */ - public boolean isIncremental() { - return incremental; - } - - /** - * Returns the chain id of published index. If {@link #isIncremental()} is {@code false}, this is the newly generated - * chain ID. - */ - public String getChainId() { - return localIndexProperties.getProperty("nexus.index.chain-id"); - } - - /** - * Returns the next chunk name about to be published. - */ - public String getNextChunkName() { - return nextChunkName; - } - - /** - * Writes out the record iterator and returns the written record count. - */ - public int writeChunk(final Iterator<Map<String, String>> iterator) throws IOException { - int written; - WritableResource writableResource = local.locate(nextChunkName); - try { - final ChunkWriter chunkWriter = new ChunkWriter(nextChunkName, writableResource.write(), INDEX_V1, new Date()); - try { - written = chunkWriter.writeChunk(iterator); - } - finally { - chunkWriter.close(); - } - if (incremental) { - // TODO: update main gz file - } - return written; + + /** + * Returns {@code true} if incremental publish is about to happen. + */ + public boolean isIncremental() + { + return incremental; } - finally { - writableResource.close(); + + /** + * Returns the chain id of published index. If {@link #isIncremental()} is {@code false}, this is the newly generated + * chain ID. + */ + public String getChainId() + { + return localIndexProperties.getProperty( "nexus.index.chain-id" ); } - } - - /** - * Closes the underlying {@link ResourceHandler} and synchronizes published index properties, so remote clients - * becomes able to consume newly published index. If sync is not desired (ie. due to aborted publish), then this - * method should NOT be invoked, but rather the {@link ResourceHandler} that caller provided in constructor of - * this class should be closed manually. - */ - public void close() throws IOException { - try { - if (incremental) { - localIndexProperties.setProperty("nexus.index.last-incremental", nextChunkCounter); - } - localIndexProperties.setProperty("nexus.index.timestamp", Utils.INDEX_DATE_FORMAT.format(new Date())); - storeProperties(local.locate(Utils.INDEX_FILE_PREFIX + ".properties"), localIndexProperties); + + /** + * Returns the next chunk name about to be published. + */ + public String getNextChunkName() + { + return nextChunkName; } - finally { - local.close(); + + /** + * Writes out the record iterator and returns the written record count. + */ + public int writeChunk( final Iterator<Map<String, String>> iterator ) + throws IOException + { + int written; + + try (WritableResource writableResource = local.locate( nextChunkName )) + { + final ChunkWriter chunkWriter = + new ChunkWriter( nextChunkName, writableResource.write(), INDEX_V1, new Date() ); + try + { + written = chunkWriter.writeChunk( iterator ); + } + finally + { + chunkWriter.close(); + } + if ( incremental ) + { + // TODO: update main gz file + } + return written; + } } - } - - /** - * Calculates the chunk names that needs to be fetched. - */ - private String calculateNextChunkCounter() { - String lastChunkCounter = localIndexProperties.getProperty("nexus.index.last-incremental"); - if (lastChunkCounter != null) { - return String.valueOf(Integer.parseInt(lastChunkCounter) + 1); + + /** + * Closes the underlying {@link ResourceHandler} and synchronizes published index properties, so remote clients + * becomes able to consume newly published index. If sync is not desired (ie. due to aborted publish), then this + * method should NOT be invoked, but rather the {@link ResourceHandler} that caller provided in constructor of + * this class should be closed manually. + */ + public void close() + throws IOException + { + try + { + if ( incremental ) + { + localIndexProperties.setProperty( "nexus.index.last-incremental", nextChunkCounter ); + } + localIndexProperties.setProperty( "nexus.index.timestamp", Utils.INDEX_DATE_FORMAT.format( new Date() ) ); + storeProperties( local.locate( Utils.INDEX_FILE_PREFIX + ".properties" ), localIndexProperties ); + } + finally + { + local.close(); + } } - else { - return "1"; + + /** + * Calculates the chunk names that needs to be fetched. + */ + private String calculateNextChunkCounter() + { + String lastChunkCounter = localIndexProperties.getProperty( "nexus.index.last-incremental" ); + if ( lastChunkCounter != null ) + { + return String.valueOf( Integer.parseInt( lastChunkCounter ) + 1 ); + } + else + { + return "1"; + } } - } } http://git-wip-us.apache.org/repos/asf/maven-indexer/blob/8d096a88/indexer-reader/src/main/java/org/apache/maven/index/reader/Record.java ---------------------------------------------------------------------- diff --git a/indexer-reader/src/main/java/org/apache/maven/index/reader/Record.java b/indexer-reader/src/main/java/org/apache/maven/index/reader/Record.java index fce1a19..e636ff1 100644 --- a/indexer-reader/src/main/java/org/apache/maven/index/reader/Record.java +++ b/indexer-reader/src/main/java/org/apache/maven/index/reader/Record.java @@ -28,385 +28,406 @@ import java.util.Map; */ public final class Record { - public static final class EntryKey<T> - { - private final String name; - - private final Class<T> proto; - - public EntryKey(final String name, final Class<T> proto) { - if (name == null) { - throw new NullPointerException("name is null"); - } - if (proto == null) { - throw new NullPointerException("proto is null"); - } - this.name = name; - this.proto = proto; + public static final class EntryKey<T> + { + private final String name; + + private final Class<T> proto; + + public EntryKey( final String name, final Class<T> proto ) + { + if ( name == null ) + { + throw new NullPointerException( "name is null" ); + } + if ( proto == null ) + { + throw new NullPointerException( "proto is null" ); + } + this.name = name; + this.proto = proto; + } + + public T coerce( final Object object ) + { + return (T) proto.cast( object ); + } + + @Override + public boolean equals( final Object o ) + { + if ( this == o ) + { + return true; + } + if ( !( o instanceof EntryKey ) ) + { + return false; + } + EntryKey entryKey = (EntryKey) o; + return name.equals( entryKey.name ); + } + + @Override + public int hashCode() + { + return name.hashCode(); + } + + @Override + public String toString() + { + return "Key{" + "name='" + name + '\'' + ", type=" + proto.getSimpleName() + '}'; + } } - public T coerce(final Object object) { - return (T) proto.cast(object); + /** + * Key of repository ID entry, that contains {@link String}. + */ + public static final EntryKey<String> REPOSITORY_ID = new EntryKey<String>( "repositoryId", String.class ); + + /** + * Key of all groups list entry, that contains {@link java.util.List<String>}. + */ + public static final EntryKey<String[]> ALL_GROUPS = new EntryKey<String[]>( "allGroups", String[].class ); + + /** + * Key of root groups list entry, that contains {@link java.util.List<String>}. + */ + public static final EntryKey<String[]> ROOT_GROUPS = new EntryKey<String[]>( "rootGroups", String[].class ); + + /** + * Key of index record modification (added to index or removed from index) timestamp entry, that contains {@link + * Long}. + */ + public static final EntryKey<Long> REC_MODIFIED = new EntryKey<Long>( "recordModified", Long.class ); + + /** + * Key of artifact groupId entry, that contains {@link String}. + */ + public static final EntryKey<String> GROUP_ID = new EntryKey<String>( "groupId", String.class ); + + /** + * Key of artifact artifactId entry, that contains {@link String}. + */ + public static final EntryKey<String> ARTIFACT_ID = new EntryKey<String>( "artifactId", String.class ); + + /** + * Key of artifact version entry, that contains {@link String}. + */ + public static final EntryKey<String> VERSION = new EntryKey<String>( "version", String.class ); + + /** + * Key of artifact classifier entry, that contains {@link String}. + */ + public static final EntryKey<String> CLASSIFIER = new EntryKey<String>( "classifier", String.class ); + + /** + * Key of artifact packaging entry, that contains {@link String}. + */ + public static final EntryKey<String> PACKAGING = new EntryKey<String>( "packaging", String.class ); + + /** + * Key of artifact file extension, that contains {@link String}. + */ + public static final EntryKey<String> FILE_EXTENSION = new EntryKey<String>( "fileExtension", String.class ); + + /** + * Key of artifact file last modified timestamp, that contains {@link Long}. + */ + public static final EntryKey<Long> FILE_MODIFIED = new EntryKey<Long>( "fileModified", Long.class ); + + /** + * Key of artifact file size in bytes, that contains {@link Long}. + */ + public static final EntryKey<Long> FILE_SIZE = new EntryKey<Long>( "fileSize", Long.class ); + + /** + * Key of artifact Sources presence flag, that contains {@link Boolean}. + */ + public static final EntryKey<Boolean> HAS_SOURCES = new EntryKey<Boolean>( "hasSources", Boolean.class ); + + /** + * Key of artifact Javadoc presence flag, that contains {@link Boolean}. + */ + public static final EntryKey<Boolean> HAS_JAVADOC = new EntryKey<Boolean>( "hasJavadoc", Boolean.class ); + + /** + * Key of artifact signature presence flag, that contains {@link Boolean}. + */ + public static final EntryKey<Boolean> HAS_SIGNATURE = new EntryKey<Boolean>( "hasSignature", Boolean.class ); + + /** + * Key of artifact name (as set in POM), that contains {@link String}. + */ + public static final EntryKey<String> NAME = new EntryKey<String>( "name", String.class ); + + /** + * Key of artifact description (as set in POM), that contains {@link String}. + */ + public static final EntryKey<String> DESCRIPTION = new EntryKey<String>( "description", String.class ); + + /** + * Key of artifact SHA1 digest, that contains {@link String}. + */ + public static final EntryKey<String> SHA1 = new EntryKey<String>( "sha1", String.class ); + + /** + * Key of artifact contained class names, that contains {@link java.util.List<String>}. Extracted by {@code + * JarFileContentsIndexCreator}. + */ + public static final EntryKey<String[]> CLASSNAMES = new EntryKey<String[]>( "classNames", String[].class ); + + /** + * Key of plugin artifact prefix, that contains {@link String}. Extracted by {@code + * MavenPluginArtifactInfoIndexCreator}. + */ + public static final EntryKey<String> PLUGIN_PREFIX = new EntryKey<String>( "pluginPrefix", String.class ); + + /** + * Key of plugin artifact goals, that contains {@link java.util.List<String>}. Extracted by {@code + * MavenPluginArtifactInfoIndexCreator}. + */ + public static final EntryKey<String[]> PLUGIN_GOALS = new EntryKey<String[]>( "pluginGoals", String[].class ); + + /** + * Key of OSGi "Bundle-SymbolicName" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_BUNDLE_SYMBOLIC_NAME = + new EntryKey<String>( "Bundle-SymbolicName", String.class ); + + /** + * Key of OSGi "Bundle-Version" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_BUNDLE_VERSION = new EntryKey<String>( "Bundle-Version", String.class ); + + /** + * Key of OSGi "Export-Package" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_EXPORT_PACKAGE = new EntryKey<String>( "Export-Package", String.class ); + + /** + * Key of OSGi "Export-Service" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_EXPORT_SERVICE = new EntryKey<String>( "Export-Service", String.class ); + + /** + * Key of OSGi "Bundle-Description" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_BUNDLE_DESCRIPTION = + new EntryKey<String>( "Bundle-Description", String.class ); + + /** + * Key of OSGi "Bundle-Name" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_BUNDLE_NAME = new EntryKey<String>( "Bundle-Name", String.class ); + + /** + * Key of OSGi "Bundle-License" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_BUNDLE_LICENSE = new EntryKey<String>( "Bundle-License", String.class ); + + /** + * Key of OSGi "Bundle-DocURL" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_EXPORT_DOCURL = new EntryKey<String>( "Bundle-DocURL", String.class ); + + /** + * Key of OSGi "Import-Package" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_IMPORT_PACKAGE = new EntryKey<String>( "Import-Package", String.class ); + + /** + * Key of OSGi "Require-Bundle" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_REQUIRE_BUNDLE = new EntryKey<String>( "Require-Bundle", String.class ); + + /** + * Key of OSGi "Provide-Capability" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_PROVIDE_CAPABILITY = + new EntryKey<String>( "Provide-Capability", String.class ); + + /** + * Key of OSGi "Require-Capability" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_REQUIRE_CAPABILITY = + new EntryKey<String>( "Require-Capability", String.class ); + + /** + * Key of OSGi "Fragment-Host" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_FRAGMENT_HOST = new EntryKey<String>( "Fragment-Host", String.class ); + + /** + * Key of deprecated OSGi "Bundle-RequiredExecutionEnvironment" manifest entry, that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> OSGI_BREE = + new EntryKey<String>( "Bundle-RequiredExecutionEnvironment", String.class ); + + /** + * Key for SHA-256 checksum needed for OSGI content capability that contains {@link String}. Extracted by {@code + * OsgiArtifactIndexCreator}. + */ + public static final EntryKey<String> SHA_256 = new EntryKey<String>( "sha256", String.class ); + + + /** + * Types of returned records returned from index. + */ + public enum Type + { + /** + * Descriptor record. Can be safely ignored. + * Contains following entries: + * <ul> + * <li>{@link #REPOSITORY_ID}</li> + * </ul> + */ + DESCRIPTOR, + + /** + * Artifact ADD record. Records of this type should be added to your indexing system. + * Contains following entries: + * <ul> + * <li>{@link #REC_MODIFIED} (when record was added/modified on index)</li> + * <li>{@link #GROUP_ID}</li> + * <li>{@link #ARTIFACT_ID}</li> + * <li>{@link #VERSION}</li> + * <li>{@link #CLASSIFIER} (optional)</li> + * <li>{@link #FILE_EXTENSION}</li> + * <li>{@link #FILE_MODIFIED}</li> + * <li>{@link #FILE_SIZE}</li> + * <li>{@link #PACKAGING}</li> + * <li>{@link #HAS_SOURCES}</li> + * <li>{@link #HAS_JAVADOC}</li> + * <li>{@link #HAS_SIGNATURE}</li> + * <li>{@link #NAME}</li> + * <li>{@link #DESCRIPTION}</li> + * <li>{@link #SHA1}</li> + * <li>{@link #CLASSNAMES} (optional)</li> + * <li>{@link #PLUGIN_PREFIX} (optional, for maven-plugins only)</li> + * <li>{@link #PLUGIN_GOALS} (optional, for maven-plugins only)</li> + * </ul> + */ + ARTIFACT_ADD, + + /** + * Artifact REMOVE record. In case of incremental updates, signals that this artifact was removed. Records of this + * type should be removed from your indexing system. + * Contains following entries: + * <ul> + * <li>{@link #REC_MODIFIED} (when record was deleted from index)</li> + * <li>{@link #GROUP_ID}</li> + * <li>{@link #ARTIFACT_ID}</li> + * <li>{@link #VERSION}</li> + * <li>{@link #CLASSIFIER} (optional)</li> + * <li>{@link #FILE_EXTENSION} (if {@link #CLASSIFIER} present)</li> + * <li>{@link #PACKAGING} (optional)</li> + * </ul> + */ + ARTIFACT_REMOVE, + + /** + * Special record, containing all the Maven "groupId"s that are enlisted on the index. Can be safely ignored. + * Contains following entries: + * <ul> + * <li>{@link #ALL_GROUPS}</li> + * </ul> + */ + ALL_GROUPS, + + /** + * Special record, containing all the root groups of Maven "groupId"s that are enlisted on the index. Can be safely + * ignored. + * Contains following entries: + * <ul> + * <li>{@link #ROOT_GROUPS}</li> + * </ul> + */ + ROOT_GROUPS } - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (!(o instanceof EntryKey)) { - return false; - } - EntryKey entryKey = (EntryKey) o; - return name.equals(entryKey.name); + private final Type type; + + private final Map<EntryKey, Object> expanded; + + public Record( final Type type, final Map<EntryKey, Object> expanded ) + { + this.type = type; + this.expanded = expanded; } - @Override - public int hashCode() { - return name.hashCode(); + /** + * Returns the {@link Type} of this record. Usually users would be interested in {@link Type#ARTIFACT_ADD} and {@link + * Type#ARTIFACT_REMOVE} types only to maintain their own index. Still, indexer offers extra records too, see {@link + * Type} for all existing types. + */ + public Type getType() + { + return type; } - @Override - public String toString() { - return "Key{" + - "name='" + name + '\'' + - ", type=" + proto.getSimpleName() + - '}'; + /** + * Returns the expanded (processed and expanded synthetic fields) record as {@link Map} ready for consumption. + */ + public Map<EntryKey, Object> getExpanded() + { + return expanded; + } + + /** + * Returns {@code true} if this record contains given {@link EntryKey}. + */ + boolean containsKey( final EntryKey<?> entryKey ) + { + return expanded.containsKey( entryKey ); + } + + /** + * Type safe handy method to get value from expanded map. + */ + public <T> T get( final EntryKey<T> entryKey ) + { + return entryKey.coerce( expanded.get( entryKey ) ); } - } - - /** - * Key of repository ID entry, that contains {@link String}. - */ - public static final EntryKey<String> REPOSITORY_ID = new EntryKey<String>("repositoryId", String.class); - - /** - * Key of all groups list entry, that contains {@link java.util.List<String>}. - */ - public static final EntryKey<String[]> ALL_GROUPS = new EntryKey<String[]>("allGroups", String[].class); - - /** - * Key of root groups list entry, that contains {@link java.util.List<String>}. - */ - public static final EntryKey<String[]> ROOT_GROUPS = new EntryKey<String[]>("rootGroups", String[].class); - - /** - * Key of index record modification (added to index or removed from index) timestamp entry, that contains {@link - * Long}. - */ - public static final EntryKey<Long> REC_MODIFIED = new EntryKey<Long>("recordModified", Long.class); - - /** - * Key of artifact groupId entry, that contains {@link String}. - */ - public static final EntryKey<String> GROUP_ID = new EntryKey<String>("groupId", String.class); - - /** - * Key of artifact artifactId entry, that contains {@link String}. - */ - public static final EntryKey<String> ARTIFACT_ID = new EntryKey<String>("artifactId", String.class); - - /** - * Key of artifact version entry, that contains {@link String}. - */ - public static final EntryKey<String> VERSION = new EntryKey<String>("version", String.class); - - /** - * Key of artifact classifier entry, that contains {@link String}. - */ - public static final EntryKey<String> CLASSIFIER = new EntryKey<String>("classifier", String.class); - - /** - * Key of artifact packaging entry, that contains {@link String}. - */ - public static final EntryKey<String> PACKAGING = new EntryKey<String>("packaging", String.class); - - /** - * Key of artifact file extension, that contains {@link String}. - */ - public static final EntryKey<String> FILE_EXTENSION = new EntryKey<String>("fileExtension", String.class); - - /** - * Key of artifact file last modified timestamp, that contains {@link Long}. - */ - public static final EntryKey<Long> FILE_MODIFIED = new EntryKey<Long>("fileModified", Long.class); - - /** - * Key of artifact file size in bytes, that contains {@link Long}. - */ - public static final EntryKey<Long> FILE_SIZE = new EntryKey<Long>("fileSize", Long.class); - - /** - * Key of artifact Sources presence flag, that contains {@link Boolean}. - */ - public static final EntryKey<Boolean> HAS_SOURCES = new EntryKey<Boolean>("hasSources", Boolean.class); - - /** - * Key of artifact Javadoc presence flag, that contains {@link Boolean}. - */ - public static final EntryKey<Boolean> HAS_JAVADOC = new EntryKey<Boolean>("hasJavadoc", Boolean.class); - - /** - * Key of artifact signature presence flag, that contains {@link Boolean}. - */ - public static final EntryKey<Boolean> HAS_SIGNATURE = new EntryKey<Boolean>("hasSignature", Boolean.class); - - /** - * Key of artifact name (as set in POM), that contains {@link String}. - */ - public static final EntryKey<String> NAME = new EntryKey<String>("name", String.class); - - /** - * Key of artifact description (as set in POM), that contains {@link String}. - */ - public static final EntryKey<String> DESCRIPTION = new EntryKey<String>("description", String.class); - - /** - * Key of artifact SHA1 digest, that contains {@link String}. - */ - public static final EntryKey<String> SHA1 = new EntryKey<String>("sha1", String.class); - - /** - * Key of artifact contained class names, that contains {@link java.util.List<String>}. Extracted by {@code - * JarFileContentsIndexCreator}. - */ - public static final EntryKey<String[]> CLASSNAMES = new EntryKey<String[]>("classNames", String[].class); - - /** - * Key of plugin artifact prefix, that contains {@link String}. Extracted by {@code - * MavenPluginArtifactInfoIndexCreator}. - */ - public static final EntryKey<String> PLUGIN_PREFIX = new EntryKey<String>("pluginPrefix", String.class); - - /** - * Key of plugin artifact goals, that contains {@link java.util.List<String>}. Extracted by {@code - * MavenPluginArtifactInfoIndexCreator}. - */ - public static final EntryKey<String[]> PLUGIN_GOALS = new EntryKey<String[]>("pluginGoals", String[].class); - - /** - * Key of OSGi "Bundle-SymbolicName" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_BUNDLE_SYMBOLIC_NAME = new EntryKey<String>("Bundle-SymbolicName", - String.class); - - /** - * Key of OSGi "Bundle-Version" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_BUNDLE_VERSION = new EntryKey<String>("Bundle-Version", String.class); - - /** - * Key of OSGi "Export-Package" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_EXPORT_PACKAGE = new EntryKey<String>("Export-Package", String.class); - - /** - * Key of OSGi "Export-Service" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_EXPORT_SERVICE = new EntryKey<String>("Export-Service", String.class); - - /** - * Key of OSGi "Bundle-Description" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_BUNDLE_DESCRIPTION = new EntryKey<String>("Bundle-Description", - String.class); - - /** - * Key of OSGi "Bundle-Name" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_BUNDLE_NAME = new EntryKey<String>("Bundle-Name", String.class); - - /** - * Key of OSGi "Bundle-License" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_BUNDLE_LICENSE = new EntryKey<String>("Bundle-License", String.class); - - /** - * Key of OSGi "Bundle-DocURL" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_EXPORT_DOCURL = new EntryKey<String>("Bundle-DocURL", String.class); - - /** - * Key of OSGi "Import-Package" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_IMPORT_PACKAGE = new EntryKey<String>("Import-Package", String.class); - - /** - * Key of OSGi "Require-Bundle" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_REQUIRE_BUNDLE = new EntryKey<String>("Require-Bundle", String.class); - - /** - * Key of OSGi "Provide-Capability" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_PROVIDE_CAPABILITY = new EntryKey<String>("Provide-Capability", String.class); - /** - * Key of OSGi "Require-Capability" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_REQUIRE_CAPABILITY = new EntryKey<String>("Require-Capability", String.class); - /** - * Key of OSGi "Fragment-Host" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_FRAGMENT_HOST = new EntryKey<String>("Fragment-Host", String.class); - /** - * Key of deprecated OSGi "Bundle-RequiredExecutionEnvironment" manifest entry, that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> OSGI_BREE = new EntryKey<String>("Bundle-RequiredExecutionEnvironment", String.class); - - /** - * Key for SHA-256 checksum needed for OSGI content capability that contains {@link String}. Extracted by {@code - * OsgiArtifactIndexCreator}. - */ - public static final EntryKey<String> SHA_256 = new EntryKey<String>("sha256", String.class); - - - /** - * Types of returned records returned from index. - */ - public enum Type - { - /** - * Descriptor record. Can be safely ignored. - * Contains following entries: - * <ul> - * <li>{@link #REPOSITORY_ID}</li> - * </ul> - */ - DESCRIPTOR, - - /** - * Artifact ADD record. Records of this type should be added to your indexing system. - * Contains following entries: - * <ul> - * <li>{@link #REC_MODIFIED} (when record was added/modified on index)</li> - * <li>{@link #GROUP_ID}</li> - * <li>{@link #ARTIFACT_ID}</li> - * <li>{@link #VERSION}</li> - * <li>{@link #CLASSIFIER} (optional)</li> - * <li>{@link #FILE_EXTENSION}</li> - * <li>{@link #FILE_MODIFIED}</li> - * <li>{@link #FILE_SIZE}</li> - * <li>{@link #PACKAGING}</li> - * <li>{@link #HAS_SOURCES}</li> - * <li>{@link #HAS_JAVADOC}</li> - * <li>{@link #HAS_SIGNATURE}</li> - * <li>{@link #NAME}</li> - * <li>{@link #DESCRIPTION}</li> - * <li>{@link #SHA1}</li> - * <li>{@link #CLASSNAMES} (optional)</li> - * <li>{@link #PLUGIN_PREFIX} (optional, for maven-plugins only)</li> - * <li>{@link #PLUGIN_GOALS} (optional, for maven-plugins only)</li> - * </ul> - */ - ARTIFACT_ADD, - - /** - * Artifact REMOVE record. In case of incremental updates, signals that this artifact was removed. Records of this - * type should be removed from your indexing system. - * Contains following entries: - * <ul> - * <li>{@link #REC_MODIFIED} (when record was deleted from index)</li> - * <li>{@link #GROUP_ID}</li> - * <li>{@link #ARTIFACT_ID}</li> - * <li>{@link #VERSION}</li> - * <li>{@link #CLASSIFIER} (optional)</li> - * <li>{@link #FILE_EXTENSION} (if {@link #CLASSIFIER} present)</li> - * <li>{@link #PACKAGING} (optional)</li> - * </ul> - */ - ARTIFACT_REMOVE, - - /** - * Special record, containing all the Maven "groupId"s that are enlisted on the index. Can be safely ignored. - * Contains following entries: - * <ul> - * <li>{@link #ALL_GROUPS}</li> - * </ul> - */ - ALL_GROUPS, - - /** - * Special record, containing all the root groups of Maven "groupId"s that are enlisted on the index. Can be safely - * ignored. - * Contains following entries: - * <ul> - * <li>{@link #ROOT_GROUPS}</li> - * </ul> - */ - ROOT_GROUPS - } - - private final Type type; - - private final Map<EntryKey, Object> expanded; - - public Record(final Type type, final Map<EntryKey, Object> expanded) { - this.type = type; - this.expanded = expanded; - } - - /** - * Returns the {@link Type} of this record. Usually users would be interested in {@link Type#ARTIFACT_ADD} and {@link - * Type#ARTIFACT_REMOVE} types only to maintain their own index. Still, indexer offers extra records too, see {@link - * Type} for all existing types. - */ - public Type getType() { - return type; - } - - /** - * Returns the expanded (processed and expanded synthetic fields) record as {@link Map} ready for consumption. - */ - public Map<EntryKey, Object> getExpanded() { - return expanded; - } - - /** - * Returns {@code true} if this record contains given {@link EntryKey}. - */ - boolean containsKey(final EntryKey<?> entryKey) { return expanded.containsKey(entryKey); } - - /** - * Type safe handy method to get value from expanded map. - */ - public <T> T get(final EntryKey<T> entryKey) { - return entryKey.coerce(expanded.get(entryKey)); - } - - /** - * Type safe handy method to put value to expanded map. Accepts {@code null} values, that removes the mapping. - */ - public <T> T put(final EntryKey<T> entryKey, final T value) { - if (value == null) { - return entryKey.coerce(expanded.remove(entryKey)); + + /** + * Type safe handy method to put value to expanded map. Accepts {@code null} values, that removes the mapping. + */ + public <T> T put( final EntryKey<T> entryKey, final T value ) + { + if ( value == null ) + { + return entryKey.coerce( expanded.remove( entryKey ) ); + } + else + { + if ( !entryKey.proto.isAssignableFrom( value.getClass() ) ) + { + throw new IllegalArgumentException( "Key " + entryKey + " does not accepts value " + value ); + } + return entryKey.coerce( expanded.put( entryKey, value ) ); + } } - else { - if (!entryKey.proto.isAssignableFrom(value.getClass())) { - throw new IllegalArgumentException("Key " + entryKey + " does not accepts value " + value); - } - return entryKey.coerce(expanded.put(entryKey, value)); + + @Override + public String toString() + { + return "Record{" + "type=" + type + ", expanded=" + expanded + '}'; } - } - - @Override - public String toString() { - return "Record{" + - "type=" + type + - ", expanded=" + expanded + - '}'; - } }
