Index: src/java/org/apache/lucene/analysis/Token.java =================================================================== --- src/java/org/apache/lucene/analysis/Token.java (revision 798431) +++ src/java/org/apache/lucene/analysis/Token.java (working copy) @@ -384,10 +384,7 @@ */ public final void setTermBuffer(char[] buffer, int offset, int length) { termText = null; - char[] newCharBuffer = growTermBuffer(length); - if (newCharBuffer != null) { - termBuffer = newCharBuffer; - } + growTermBuffer(length); System.arraycopy(buffer, offset, termBuffer, 0, length); termLength = length; } @@ -397,11 +394,8 @@ */ public final void setTermBuffer(String buffer) { termText = null; - int length = buffer.length(); - char[] newCharBuffer = growTermBuffer(length); - if (newCharBuffer != null) { - termBuffer = newCharBuffer; - } + final int length = buffer.length(); + growTermBuffer(length); buffer.getChars(0, length, termBuffer, 0); termLength = length; } @@ -416,10 +410,7 @@ assert offset <= buffer.length(); assert offset + length <= buffer.length(); termText = null; - char[] newCharBuffer = growTermBuffer(length); - if (newCharBuffer != null) { - termBuffer = newCharBuffer; - } + growTermBuffer(length); buffer.getChars(offset, offset + length, termBuffer, 0); termLength = length; } @@ -447,76 +438,68 @@ * @return newly created termBuffer with length >= newSize */ public char[] resizeTermBuffer(int newSize) { - char[] newCharBuffer = growTermBuffer(newSize); if (termBuffer == null) { - // If there were termText, then preserve it. - // note that if termBuffer is null then newCharBuffer cannot be null - assert newCharBuffer != null; + // The buffer is always at least MIN_BUFFER_SIZE + newSize = newSize < MIN_BUFFER_SIZE ? MIN_BUFFER_SIZE : newSize; + //Preserve termText if (termText != null) { - termText.getChars(0, termText.length(), newCharBuffer, 0); + final int ttLen = termText.length(); + newSize = newSize < ttLen ? ttLen : newSize; + termBuffer = new char[ArrayUtil.getNextSize(newSize)]; + termText.getChars(0, termText.length(), termBuffer, 0); + termText = null; + } else { // no term Text, the first allocation + termBuffer = new char[ArrayUtil.getNextSize(newSize)]; + } + } else { + if(termBuffer.length < newSize){ + // Not big enough; create a new array with slight + // over allocation and preserve content + final char[] newCharBuffer = new char[ArrayUtil.getNextSize(newSize)]; + System.arraycopy(termBuffer, 0, newCharBuffer, 0, termBuffer.length); + termBuffer = newCharBuffer; } - termBuffer = newCharBuffer; - } else if (newCharBuffer != null) { - // Note: if newCharBuffer != null then termBuffer needs to grow. - // If there were a termBuffer, then preserve it - System.arraycopy(termBuffer, 0, newCharBuffer, 0, termBuffer.length); - termBuffer = newCharBuffer; - } - termText = null; - return termBuffer; + } + return termBuffer; } - /** Allocates a buffer char[] of at least newSize + /** Allocates a buffer char[] of at least newSize, without preserving the existing content. + * its always used in places that set the content * @param newSize minimum size of the buffer - * @return newly created buffer with length >= newSize or null if the current termBuffer is big enough */ - private char[] growTermBuffer(int newSize) { - if (termBuffer != null) { - if (termBuffer.length >= newSize) - // Already big enough - return null; - else + private void growTermBuffer(int newSize) { + if (termBuffer == null) { + // The buffer is always at least MIN_BUFFER_SIZE + termBuffer = new char[ArrayUtil.getNextSize(newSize < MIN_BUFFER_SIZE ? MIN_BUFFER_SIZE : newSize)]; + } else { + if(termBuffer.length < newSize){ // Not big enough; create a new array with slight // over allocation: - return new char[ArrayUtil.getNextSize(newSize)]; - } else { - - // determine the best size - // The buffer is always at least MIN_BUFFER_SIZE - if (newSize < MIN_BUFFER_SIZE) { - newSize = MIN_BUFFER_SIZE; + termBuffer = new char[ArrayUtil.getNextSize(newSize)]; } - - // If there is already a termText, then the size has to be at least that big - if (termText != null) { - int ttLength = termText.length(); - if (newSize < ttLength) { - newSize = ttLength; - } - } - - return new char[newSize]; - } + } } + // TODO: once we remove the deprecated termText() method // and switch entirely to char[] termBuffer we don't need - // to use this method anymore + // to use this method anymore, only for late init of the buffer private void initTermBuffer() { if (termBuffer == null) { if (termText == null) { - termBuffer = new char[MIN_BUFFER_SIZE]; + termBuffer = new char[ArrayUtil.getNextSize(MIN_BUFFER_SIZE)]; termLength = 0; } else { int length = termText.length(); if (length < MIN_BUFFER_SIZE) length = MIN_BUFFER_SIZE; - termBuffer = new char[length]; + termBuffer = new char[ArrayUtil.getNextSize(length)]; termLength = termText.length(); termText.getChars(0, termText.length(), termBuffer, 0); termText = null; } - } else if (termText != null) + } else { termText = null; + } } /** Return number of valid characters (length of the term) @@ -660,7 +643,7 @@ t.termBuffer = (char[]) termBuffer.clone(); } if (payload != null) { - t.setPayload((Payload) payload.clone()); + t.payload = (Payload) payload.clone(); } return t; } @@ -876,5 +859,9 @@ public void copyTo(AttributeImpl target) { Token to = (Token) target; to.reinit(this); + // reinit shares the payload, so clone it: + if (payload !=null) { + to.payload = (Payload) payload.clone(); + } } } Index: src/java/org/apache/lucene/analysis/tokenattributes/TermAttributeImpl.java =================================================================== --- src/java/org/apache/lucene/analysis/tokenattributes/TermAttributeImpl.java (revision 798431) +++ src/java/org/apache/lucene/analysis/tokenattributes/TermAttributeImpl.java (working copy) @@ -52,10 +52,7 @@ * @param length the number of characters to copy */ public void setTermBuffer(char[] buffer, int offset, int length) { - char[] newCharBuffer = growTermBuffer(length); - if (newCharBuffer != null) { - termBuffer = newCharBuffer; - } + growTermBuffer(length); System.arraycopy(buffer, offset, termBuffer, 0, length); termLength = length; } @@ -65,10 +62,7 @@ */ public void setTermBuffer(String buffer) { int length = buffer.length(); - char[] newCharBuffer = growTermBuffer(length); - if (newCharBuffer != null) { - termBuffer = newCharBuffer; - } + growTermBuffer(length); buffer.getChars(0, length, termBuffer, 0); termLength = length; } @@ -82,10 +76,7 @@ public void setTermBuffer(String buffer, int offset, int length) { assert offset <= buffer.length(); assert offset + length <= buffer.length(); - char[] newCharBuffer = growTermBuffer(length); - if (newCharBuffer != null) { - termBuffer = newCharBuffer; - } + growTermBuffer(length); buffer.getChars(offset, offset + length, termBuffer, 0); termLength = length; } @@ -113,53 +104,43 @@ * @return newly created termBuffer with length >= newSize */ public char[] resizeTermBuffer(int newSize) { - char[] newCharBuffer = growTermBuffer(newSize); if (termBuffer == null) { - // If there were termText, then preserve it. - // note that if termBuffer is null then newCharBuffer cannot be null - assert newCharBuffer != null; - termBuffer = newCharBuffer; - } else if (newCharBuffer != null) { - // Note: if newCharBuffer != null then termBuffer needs to grow. - // If there were a termBuffer, then preserve it - System.arraycopy(termBuffer, 0, newCharBuffer, 0, termBuffer.length); - termBuffer = newCharBuffer; - } - return termBuffer; + // The buffer is always at least MIN_BUFFER_SIZE + termBuffer = new char[ArrayUtil.getNextSize(newSize < MIN_BUFFER_SIZE ? MIN_BUFFER_SIZE : newSize)]; + } else { + if(termBuffer.length < newSize){ + // Not big enough; create a new array with slight + // over allocation and preserve content + final char[] newCharBuffer = new char[ArrayUtil.getNextSize(newSize)]; + System.arraycopy(termBuffer, 0, newCharBuffer, 0, termBuffer.length); + termBuffer = newCharBuffer; + } + } + return termBuffer; } - /** Allocates a buffer char[] of at least newSize + + /** Allocates a buffer char[] of at least newSize, without preserving the existing content. + * its always used in places that set the content * @param newSize minimum size of the buffer - * @return newly created buffer with length >= newSize or null if the current termBuffer is big enough */ - private char[] growTermBuffer(int newSize) { - if (termBuffer != null) { - if (termBuffer.length >= newSize) - // Already big enough - return null; - else + private void growTermBuffer(int newSize) { + if (termBuffer == null) { + // The buffer is always at least MIN_BUFFER_SIZE + termBuffer = new char[ArrayUtil.getNextSize(newSize < MIN_BUFFER_SIZE ? MIN_BUFFER_SIZE : newSize)]; + } else { + if(termBuffer.length < newSize){ // Not big enough; create a new array with slight // over allocation: - return new char[ArrayUtil.getNextSize(newSize)]; - } else { - - // determine the best size - // The buffer is always at least MIN_BUFFER_SIZE - if (newSize < MIN_BUFFER_SIZE) { - newSize = MIN_BUFFER_SIZE; + termBuffer = new char[ArrayUtil.getNextSize(newSize)]; } - - return new char[newSize]; - } + } } - - // TODO: once we remove the deprecated termText() method - // and switch entirely to char[] termBuffer we don't need - // to use this method anymore + private void initTermBuffer() { if (termBuffer == null) { - termBuffer = new char[MIN_BUFFER_SIZE]; - termLength = 0; + termBuffer = new char[ArrayUtil.getNextSize(MIN_BUFFER_SIZE)]; + termLength = 0; } } Index: src/java/org/apache/lucene/util/AttributeImpl.java =================================================================== --- src/java/org/apache/lucene/util/AttributeImpl.java (revision 798431) +++ src/java/org/apache/lucene/util/AttributeImpl.java (working copy) @@ -19,6 +19,7 @@ import java.io.Serializable; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; /** * Base class for Attributes that can be added to a @@ -53,16 +54,17 @@ try { for (int i = 0; i < fields.length; i++) { Field f = fields[i]; + if (Modifier.isStatic(f.getModifiers())) continue; f.setAccessible(true); Object value = f.get(this); + if (buffer.length()>0) { + buffer.append(','); + } if (value == null) { buffer.append(f.getName() + "=null"); } else { buffer.append(f.getName() + "=" + value); } - if (i < fields.length - 1) { - buffer.append(','); - } } } catch (IllegalAccessException e) { // this should never happen, because we're just accessing fields Index: src/test/org/apache/lucene/analysis/TestToken.java =================================================================== --- src/test/org/apache/lucene/analysis/TestToken.java (revision 798431) +++ src/test/org/apache/lucene/analysis/TestToken.java (working copy) @@ -17,9 +17,10 @@ * limitations under the License. */ +import org.apache.lucene.index.Payload; +import org.apache.lucene.analysis.tokenattributes.TestSimpleAttributeImpls; import org.apache.lucene.util.LuceneTestCase; -/** @deprecated */ public class TestToken extends LuceneTestCase { public TestToken(String name) { @@ -122,7 +123,7 @@ buf.append("a"); } assertEquals(20000, t.termLength()); - assertEquals(20331, t.termBuffer().length); + assertEquals(20167, t.termBuffer().length); // Test for slow growth to a long term t = new Token(); @@ -136,7 +137,7 @@ buf.append("a"); } assertEquals(20000, t.termLength()); - assertEquals(20331, t.termBuffer().length); + assertEquals(20167, t.termBuffer().length); } public void testToString() throws Exception { @@ -172,7 +173,30 @@ char[] content = "hello".toCharArray(); t.setTermBuffer(content, 0, 5); char[] buf = t.termBuffer(); - Token copy = (Token) t.clone(); + Token copy = (Token) TestSimpleAttributeImpls.assertCloneIsEqual(t); + assertEquals(t.term(), copy.term()); assertNotSame(buf, copy.termBuffer()); + + Payload pl = new Payload(new byte[]{1,2,3,4}); + t.setPayload(pl); + copy = (Token) TestSimpleAttributeImpls.assertCloneIsEqual(t); + assertEquals(pl, copy.getPayload()); + assertNotSame(pl, copy.getPayload()); } + + public void testCopyTo() throws Exception { + Token t = new Token(0, 5); + char[] content = "hello".toCharArray(); + t.setTermBuffer(content, 0, 5); + char[] buf = t.termBuffer(); + Token copy = (Token) TestSimpleAttributeImpls.assertCopyIsEqual(t); + assertEquals(t.term(), copy.term()); + assertNotSame(buf, copy.termBuffer()); + + Payload pl = new Payload(new byte[]{1,2,3,4}); + t.setPayload(pl); + copy = (Token) TestSimpleAttributeImpls.assertCopyIsEqual(t); + assertEquals(pl, copy.getPayload()); + assertNotSame(pl, copy.getPayload()); + } } Index: src/test/org/apache/lucene/analysis/tokenattributes/TestSimpleAttributeImpls.java =================================================================== --- src/test/org/apache/lucene/analysis/tokenattributes/TestSimpleAttributeImpls.java (revision 0) +++ src/test/org/apache/lucene/analysis/tokenattributes/TestSimpleAttributeImpls.java (revision 0) @@ -0,0 +1,136 @@ +package org.apache.lucene.analysis.tokenattributes; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.lucene.index.Payload; +import org.apache.lucene.util.AttributeImpl; +import org.apache.lucene.util.LuceneTestCase; + +public class TestSimpleAttributeImpls extends LuceneTestCase { + + public TestSimpleAttributeImpls(String name) { + super(name); + } + + public void testFlagsAttribute() throws Exception { + FlagsAttributeImpl att = new FlagsAttributeImpl(); + assertEquals(0, att.getFlags()); + + att.setFlags(1234); + assertEquals("flags=1234", att.toString()); + + FlagsAttributeImpl att2 = (FlagsAttributeImpl) assertCloneIsEqual(att); + assertEquals(1234, att2.getFlags()); + + att2 = (FlagsAttributeImpl) assertCopyIsEqual(att); + assertEquals(1234, att2.getFlags()); + + att.clear(); + assertEquals(0, att.getFlags()); + } + + public void testPositionIncrementAttribute() throws Exception { + PositionIncrementAttributeImpl att = new PositionIncrementAttributeImpl(); + assertEquals(1, att.getPositionIncrement()); + + att.setPositionIncrement(1234); + assertEquals("positionIncrement=1234", att.toString()); + + PositionIncrementAttributeImpl att2 = (PositionIncrementAttributeImpl) assertCloneIsEqual(att); + assertEquals(1234, att2.getPositionIncrement()); + + att2 = (PositionIncrementAttributeImpl) assertCopyIsEqual(att); + assertEquals(1234, att2.getPositionIncrement()); + + att.clear(); + assertEquals(1, att.getPositionIncrement()); + } + + public void testTypeAttribute() throws Exception { + TypeAttributeImpl att = new TypeAttributeImpl(); + assertEquals(TypeAttributeImpl.DEFAULT_TYPE, att.type()); + + att.setType("hallo"); + assertEquals("type=hallo", att.toString()); + + TypeAttributeImpl att2 = (TypeAttributeImpl) assertCloneIsEqual(att); + assertEquals("hallo", att2.type()); + + att2 = (TypeAttributeImpl) assertCopyIsEqual(att); + assertEquals("hallo", att2.type()); + + att.clear(); + assertEquals(TypeAttributeImpl.DEFAULT_TYPE, att.type()); + } + + public void testPayloadAttribute() throws Exception { + PayloadAttributeImpl att = new PayloadAttributeImpl(); + assertNull(att.getPayload()); + + Payload pl = new Payload(new byte[]{1,2,3,4}); + att.setPayload(pl); + + PayloadAttributeImpl att2 = (PayloadAttributeImpl) assertCloneIsEqual(att); + assertEquals(pl, att2.getPayload()); + assertNotSame(pl, att2.getPayload()); + + att2 = (PayloadAttributeImpl) assertCopyIsEqual(att); + assertEquals(pl, att2.getPayload()); + assertNotSame(pl, att2.getPayload()); + + att.clear(); + assertNull(att.getPayload()); + } + + public void testOffsetAttribute() throws Exception { + OffsetAttributeImpl att = new OffsetAttributeImpl(); + assertEquals(0, att.startOffset()); + assertEquals(0, att.endOffset()); + + att.setOffset(12, 34); + // no string test here, because order unknown + + OffsetAttributeImpl att2 = (OffsetAttributeImpl) assertCloneIsEqual(att); + assertEquals(12, att2.startOffset()); + assertEquals(34, att2.endOffset()); + + att2 = (OffsetAttributeImpl) assertCopyIsEqual(att); + assertEquals(12, att2.startOffset()); + assertEquals(34, att2.endOffset()); + + att.clear(); + assertEquals(0, att.startOffset()); + assertEquals(0, att.endOffset()); + } + + public static final AttributeImpl assertCloneIsEqual(AttributeImpl att) { + AttributeImpl clone = (AttributeImpl) att.clone(); + assertEquals("Clone must be equal", att, clone); + assertEquals("Clone's hashcode must be equal", att.hashCode(), clone.hashCode()); + return clone; + } + + public static final AttributeImpl assertCopyIsEqual(AttributeImpl att) throws Exception { + AttributeImpl copy = (AttributeImpl) att.getClass().newInstance(); + att.copyTo(copy); + assertEquals("Copied instance must be equal", att, copy); + assertEquals("Copied instance's hashcode must be equal", att.hashCode(), copy.hashCode()); + return copy; + } + +} Property changes on: src\test\org\apache\lucene\analysis\tokenattributes\TestSimpleAttributeImpls.java ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Index: src/test/org/apache/lucene/analysis/tokenattributes/TestTermAttributeImpl.java =================================================================== --- src/test/org/apache/lucene/analysis/tokenattributes/TestTermAttributeImpl.java (revision 0) +++ src/test/org/apache/lucene/analysis/tokenattributes/TestTermAttributeImpl.java (working copy) @@ -1,4 +1,4 @@ -package org.apache.lucene.analysis; +package org.apache.lucene.analysis.tokenattributes; /** * Licensed to the Apache Software Foundation (ASF) under one or more @@ -19,45 +19,14 @@ import org.apache.lucene.util.LuceneTestCase; -/** @deprecated */ -public class TestToken extends LuceneTestCase { +public class TestTermAttributeImpl extends LuceneTestCase { - public TestToken(String name) { + public TestTermAttributeImpl(String name) { super(name); } - public void testCtor() throws Exception { - Token t = new Token(); - char[] content = "hello".toCharArray(); - t.setTermBuffer(content, 0, content.length); - char[] buf = t.termBuffer(); - assertNotSame(t.termBuffer(), content); - assertEquals("hello", t.term()); - assertEquals("word", t.type()); - assertEquals(0, t.getFlags()); - - t = new Token(6, 22); - t.setTermBuffer(content, 0, content.length); - assertEquals("hello", t.term()); - assertEquals("(hello,6,22)", t.toString()); - assertEquals("word", t.type()); - assertEquals(0, t.getFlags()); - - t = new Token(6, 22, 7); - t.setTermBuffer(content, 0, content.length); - assertEquals("hello", t.term()); - assertEquals("(hello,6,22)", t.toString()); - assertEquals(7, t.getFlags()); - - t = new Token(6, 22, "junk"); - t.setTermBuffer(content, 0, content.length); - assertEquals("hello", t.term()); - assertEquals("(hello,6,22,type=junk)", t.toString()); - assertEquals(0, t.getFlags()); - } - public void testResize() { - Token t = new Token(); + TermAttributeImpl t = new TermAttributeImpl(); char[] content = "hello".toCharArray(); t.setTermBuffer(content, 0, content.length); for (int i = 0; i < 2000; i++) @@ -69,7 +38,7 @@ } public void testGrow() { - Token t = new Token(); + TermAttributeImpl t = new TermAttributeImpl(); StringBuffer buf = new StringBuffer("ab"); for (int i = 0; i < 20; i++) { @@ -83,7 +52,7 @@ assertEquals(1179654, t.termBuffer().length); // now as a string, first variant - t = new Token(); + t = new TermAttributeImpl(); buf = new StringBuffer("ab"); for (int i = 0; i < 20; i++) { @@ -97,7 +66,7 @@ assertEquals(1179654, t.termBuffer().length); // now as a string, second variant - t = new Token(); + t = new TermAttributeImpl(); buf = new StringBuffer("ab"); for (int i = 0; i < 20; i++) { @@ -111,7 +80,7 @@ assertEquals(1179654, t.termBuffer().length); // Test for slow growth to a long term - t = new Token(); + t = new TermAttributeImpl(); buf = new StringBuffer("a"); for (int i = 0; i < 20000; i++) { @@ -122,10 +91,10 @@ buf.append("a"); } assertEquals(20000, t.termLength()); - assertEquals(20331, t.termBuffer().length); + assertEquals(20167, t.termBuffer().length); // Test for slow growth to a long term - t = new Token(); + t = new TermAttributeImpl(); buf = new StringBuffer("a"); for (int i = 0; i < 20000; i++) { @@ -136,43 +105,54 @@ buf.append("a"); } assertEquals(20000, t.termLength()); - assertEquals(20331, t.termBuffer().length); + assertEquals(20167, t.termBuffer().length); } public void testToString() throws Exception { char[] b = {'a', 'l', 'o', 'h', 'a'}; - Token t = new Token("", 0, 5); + TermAttributeImpl t = new TermAttributeImpl(); t.setTermBuffer(b, 0, 5); - assertEquals("(aloha,0,5)", t.toString()); + assertEquals("term=aloha", t.toString()); - t.setTermText("hi there"); - assertEquals("(hi there,0,5)", t.toString()); + t.setTermBuffer("hi there"); + assertEquals("term=hi there", t.toString()); } public void testMixedStringArray() throws Exception { - Token t = new Token("hello", 0, 5); - assertEquals(t.termText(), "hello"); + TermAttributeImpl t = new TermAttributeImpl(); + t.setTermBuffer("hello"); assertEquals(t.termLength(), 5); assertEquals(t.term(), "hello"); - t.setTermText("hello2"); + t.setTermBuffer("hello2"); assertEquals(t.termLength(), 6); assertEquals(t.term(), "hello2"); t.setTermBuffer("hello3".toCharArray(), 0, 6); - assertEquals(t.termText(), "hello3"); + assertEquals(t.term(), "hello3"); // Make sure if we get the buffer and change a character - // that termText() reflects the change + // that term() reflects the change char[] buffer = t.termBuffer(); buffer[1] = 'o'; - assertEquals(t.termText(), "hollo3"); + assertEquals(t.term(), "hollo3"); } public void testClone() throws Exception { - Token t = new Token(0, 5); + TermAttributeImpl t = new TermAttributeImpl(); char[] content = "hello".toCharArray(); t.setTermBuffer(content, 0, 5); char[] buf = t.termBuffer(); - Token copy = (Token) t.clone(); + TermAttributeImpl copy = (TermAttributeImpl) TestSimpleAttributeImpls.assertCloneIsEqual(t); + assertEquals(t.term(), copy.term()); assertNotSame(buf, copy.termBuffer()); } + + public void testCopyTo() throws Exception { + TermAttributeImpl t = new TermAttributeImpl(); + char[] content = "hello".toCharArray(); + t.setTermBuffer(content, 0, 5); + char[] buf = t.termBuffer(); + TermAttributeImpl copy = (TermAttributeImpl) TestSimpleAttributeImpls.assertCopyIsEqual(t); + assertEquals(t.term(), copy.term()); + assertNotSame(buf, copy.termBuffer()); + } }