From: <my...@us...> - 2010-08-26 14:56:17
|
Revision: 2416 http://aperture.svn.sourceforge.net/aperture/?rev=2416&view=rev Author: mylka Date: 2010-08-26 14:56:10 +0000 (Thu, 26 Aug 2010) Log Message: ----------- [3041877] something even better than AttachmentsOnlyMode, i've come up with MultiLevel mode for the VcardSubcrawler Modified Paths: -------------- aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawler.java aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawlerFactory.java aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawlerTest.java Added Paths: ----------- aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/util/ByteArrayCharSequence.java aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/util/ByteArrayCharSequenceTest.java aperture/trunk/core/src/test/resources/org/semanticdesktop/aperture/docs/vcard-vCards-SAP-markussprung.vcf Modified: aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawler.java =================================================================== --- aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawler.java 2010-08-26 11:37:05 UTC (rev 2415) +++ aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawler.java 2010-08-26 14:56:10 UTC (rev 2416) @@ -16,9 +16,13 @@ import java.net.URISyntaxException; import java.nio.charset.Charset; import java.text.ParseException; +import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import net.fortuna.ical4j.data.ParserException; import net.fortuna.ical4j.model.ValidationException; import net.fortuna.ical4j.util.CompatibilityHints; import net.fortuna.ical4j.vcard.Group; @@ -72,6 +76,7 @@ import org.semanticdesktop.aperture.subcrawler.SubCrawlerHandler; import org.semanticdesktop.aperture.subcrawler.SubCrawlerUtil; import org.semanticdesktop.aperture.subcrawler.base.AbstractSubCrawler; +import org.semanticdesktop.aperture.util.ByteArrayCharSequence; import org.semanticdesktop.aperture.util.DateUtil; import org.semanticdesktop.aperture.util.IOUtil; import org.semanticdesktop.aperture.util.StringUtil; @@ -133,6 +138,18 @@ private Logger logger = LoggerFactory.getLogger(this.getClass()); + private static final Pattern VCARD_START_PATTERN = Pattern.compile("BEGIN:VCARD"); + + private boolean multiLevelMode; + + public VcardSubCrawler() { + this(false); + } + + public VcardSubCrawler(boolean multiLevelMode) { + this.multiLevelMode = multiLevelMode; + } + /** * @see SubCrawler#subCrawl(URI, InputStream, SubCrawlerHandler, DataSource, AccessData, Charset, String, RDFContainer) */ @@ -148,49 +165,58 @@ try { // first read the whole stream into a byte array - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - IOUtil.writeStream(stream, baos); - byte [] bytes = baos.toByteArray(); + byte [] bytes = IOUtil.readBytes(stream); - // add the fulltext, before the parser is invoked, so that // the fulltext is added regardless of the whether the file // is parseable or not try { String fulltext = new String(bytes, "UTF-8"); - parentMetadata.add(NIE.plainTextContent,fulltext); + parentMetadata.put(NIE.plainTextContent,fulltext); } catch (Exception e) { logger.warn("Couldn't add the fulltext of the vcard file",e); } - - Reader reader = new InputStreamReader(new ByteArrayInputStream(bytes)); - GroupRegistry groupRegistry = new GroupRegistry(); - PropertyFactoryRegistry propReg = new PropertyFactoryRegistry(); - ParameterFactoryRegistry parReg = new ParameterFactoryRegistry(); - - addTypeParamsToRegistry(parReg); - addCardpicturePropertyToRegistry(propReg); - CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING, true); - CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true); - CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION, true); - CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_OUTLOOK_COMPATIBILITY, true); - CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_NOTES_COMPATIBILITY, true); - VCardBuilder builder = new VCardBuilder(reader,groupRegistry,propReg,parReg); - List<VCard> cards = builder.buildAll(); - VCardOutputter outputter = new VCardOutputter(false); - if (cards.size() == 1) { - processContact(cards.get(0), parentMetadata, parentMetadata.getDescribedUri(), handler, accessData, dataSource, outputter); - } - else { - processAddressBook(cards, parentMetadata, handler, outputter, accessData, dataSource); - } + ArrayList<Integer> indexes = new ArrayList<Integer>(); + Matcher matcher = VCARD_START_PATTERN.matcher(new ByteArrayCharSequence(bytes)); + while (matcher.find()) { + indexes.add(matcher.start()); + } + VCardOutputter outputter = new VCardOutputter(false); + + if (indexes.size() == 0) { + throw new SubCrawlerException("Couldn't find a BEGIN:VCARD block in the file"); + } else if (indexes.size() == 1){ + Reader reader = new InputStreamReader(new ByteArrayInputStream(bytes,indexes.get(0),bytes.length - indexes.get(0))); + VCardBuilder builder = createVcardBuilder(reader); + VCard vcard = builder.build(); + processContact(vcard, parentMetadata, parentMetadata.getDescribedUri(), handler, accessData, dataSource, outputter); + } else { + processAddressBook(bytes, indexes, parentMetadata, handler, outputter, accessData, dataSource); + } } catch (Exception e) { logger.warn("Error while parsing vcard: " + parentMetadata.getDescribedUri(),e); } } + private VCardBuilder createVcardBuilder(Reader reader) { + GroupRegistry groupRegistry = new GroupRegistry(); + PropertyFactoryRegistry propReg = new PropertyFactoryRegistry(); + ParameterFactoryRegistry parReg = new ParameterFactoryRegistry(); + + addTypeParamsToRegistry(parReg); + addCardpicturePropertyToRegistry(propReg); + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING, true); + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true); + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION, true); + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_OUTLOOK_COMPATIBILITY, true); + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_NOTES_COMPATIBILITY, true); + + VCardBuilder builder = new VCardBuilder(reader,groupRegistry,propReg,parReg); + return builder; + } + private void addTypeParamsToRegistry(ParameterFactoryRegistry parReg) { for (final String name : new String[] {"HOME","WORK","MSG","PREF","VOICE","FAX","CELL", "VIDEO","PAGER","BBS","MODEM","CAR","ISDN","PCS","INTERNET","X400","DOM", @@ -247,20 +273,36 @@ return VcardSubCrawlerFactory.VCARD_URI_PREFIX; } - private void processAddressBook(List<VCard> contacts, RDFContainer parentMetadata, - SubCrawlerHandler handler, VCardOutputter out, AccessData accessData, DataSource source) { + private void processAddressBook(byte [] bytes, List<Integer> indexes, RDFContainer parentMetadata, + SubCrawlerHandler handler, VCardOutputter out, AccessData accessData, DataSource source) throws IOException, ParserException { parentMetadata.add(RDF.type, NCO.ContactList); - for (VCard contact : contacts) { + for (int i = 0; i < indexes.size(); i++) { + int start = indexes.get(i); + int length = bytes.length - start; + if (i < indexes.size() - 1) { + length = indexes.get(i+1) - indexes.get(i); + } + Reader reader = new InputStreamReader(new ByteArrayInputStream(bytes,start,length)); + VCardBuilder builder = createVcardBuilder(reader); + VCard contact = builder.build(); + try { String contactHash = getContactHash(contact, out); URI contactUri = generateURIForContact(contact, parentMetadata, contactHash); RDFContainerFactory factory = handler.getRDFContainerFactory(contactUri.toString()); RDFContainer container = factory.getRDFContainer(contactUri); - processContact(contact, container, contactUri, handler, accessData, source, out); parentMetadata.add(NCO.containsContact, contactUri); container.add(RDF.type, NCO.ContactListDataObject); container.add(NIE.isPartOf, parentMetadata.getDescribedUri()); - passMetadataToHandler(container, handler, contactHash, accessData, source); + + if (multiLevelMode) { + passFileDataObjectToHandler(container, bytes, start, length, handler, + contactHash, accessData, source); + } else { + processContact(contact, container, contactUri, handler, accessData, source, out); + passMetadataToHandler(container, handler, contactHash, accessData, source); + } + } catch (Exception e) { logger.warn("Failed to process vcard",e); } @@ -287,6 +329,26 @@ } } + private void passFileDataObjectToHandler(RDFContainer container, byte [] buf, int start, int length, SubCrawlerHandler handler, String objectHash, + AccessData accessData, DataSource source) { + URI uri = container.getDescribedUri(); + DataObject object = new FileDataObjectBase(uri, source, container, new ByteArrayInputStream(buf,start,length)); + if (accessData == null) { + handler.objectNew(object); + } else if (!accessData.isKnownId(uri.toString())) { + accessData.put(uri.toString(), OBJECT_HASH_KEY, objectHash); + handler.objectNew(object); + } else { + String oldHash = accessData.get(uri.toString(), OBJECT_HASH_KEY); + if (oldHash == null || !oldHash.equals(objectHash)) { + accessData.put(uri.toString(), OBJECT_HASH_KEY, objectHash); + handler.objectChanged(object); + } else { + handler.objectNotModified(uri.toString()); + } + } + } + private void passAttachmentToHandler(RDFContainer container, SubCrawlerHandler handler, String attachmentHash, AccessData accessData, DataSource source, byte [] bytes) { URI uri = container.getDescribedUri(); Modified: aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawlerFactory.java =================================================================== --- aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawlerFactory.java 2010-08-26 11:37:05 UTC (rev 2415) +++ aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawlerFactory.java 2010-08-26 14:56:10 UTC (rev 2416) @@ -14,6 +14,16 @@ import org.semanticdesktop.aperture.subcrawler.SubCrawlerFactory; public class VcardSubCrawlerFactory implements SubCrawlerFactory { + + private boolean multiLevelMode = false; + + public VcardSubCrawlerFactory() { + this(false); + } + + public VcardSubCrawlerFactory(boolean multiLevelMode) { + this.multiLevelMode = multiLevelMode; + } private static final Set MIME_TYPES; @@ -27,7 +37,7 @@ } public SubCrawler get() { - return new VcardSubCrawler(); + return new VcardSubCrawler(multiLevelMode); } public Set getSupportedMimeTypes() { Added: aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/util/ByteArrayCharSequence.java =================================================================== --- aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/util/ByteArrayCharSequence.java (rev 0) +++ aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/util/ByteArrayCharSequence.java 2010-08-26 14:56:10 UTC (rev 2416) @@ -0,0 +1,56 @@ +package org.semanticdesktop.aperture.util; + +import java.io.UnsupportedEncodingException; + +import org.apache.commons.lang.NullArgumentException; + +public class ByteArrayCharSequence implements CharSequence { + + private byte [] buf; + private int startIdx; + private int endIdx; + + public ByteArrayCharSequence(byte[] bs) { + this(bs,0,bs.length); + } + + private ByteArrayCharSequence(byte [] bs, int startIdx, int endIdx) { + if (bs == null) { + throw new NullArgumentException("bs cannot be null"); + } + if (startIdx < 0 || startIdx > endIdx || endIdx > bs.length) { + throw new IllegalArgumentException("The indices should be : 0 <= startIdx <= endIdx < " + bs.length); + } + this.buf = bs; + this.startIdx = startIdx; + this.endIdx = endIdx; + } + + public char charAt(int index) { + if (index < 0 || index >= endIdx - startIdx) { + throw new IndexOutOfBoundsException("Index " + index + " not between 0 and " + (endIdx - startIdx)); + } + return (char)(buf[startIdx + index] & 0xFF); + } + + public int length() { + return endIdx - startIdx; + } + + public CharSequence subSequence(int start, int end) { + + if (start < 0 || start > end || end > endIdx - startIdx) { + throw new IllegalArgumentException("The indices should be : 0 <= start <= end < " + length()); + } + + return new ByteArrayCharSequence(buf,startIdx + start,startIdx + end); + } + + public String toString() { + try { + return new String(buf,"ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); // this will not happen + } + } +} Property changes on: aperture/trunk/core/src/main/java/org/semanticdesktop/aperture/util/ByteArrayCharSequence.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawlerTest.java =================================================================== --- aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawlerTest.java 2010-08-26 11:37:05 UTC (rev 2415) +++ aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/subcrawler/vcard/VcardSubCrawlerTest.java 2010-08-26 14:56:10 UTC (rev 2416) @@ -8,6 +8,7 @@ import java.io.InputStream; import java.net.URISyntaxException; +import java.util.Arrays; import java.util.Iterator; import java.util.Set; @@ -29,15 +30,21 @@ import org.ontoware.rdf2go.model.node.impl.URIImpl; import org.ontoware.rdf2go.vocabulary.RDF; import org.semanticdesktop.aperture.accessor.AccessData; +import org.semanticdesktop.aperture.accessor.DataObject; +import org.semanticdesktop.aperture.accessor.FileDataObject; import org.semanticdesktop.aperture.accessor.base.AccessDataImpl; +import org.semanticdesktop.aperture.accessor.base.RDFContainerFactoryImpl; import org.semanticdesktop.aperture.extractor.ExtractorRegistry; import org.semanticdesktop.aperture.extractor.impl.DefaultExtractorRegistry; import org.semanticdesktop.aperture.rdf.RDFContainer; import org.semanticdesktop.aperture.rdf.impl.RDFContainerImpl; import org.semanticdesktop.aperture.subcrawler.SubCrawlerRegistry; +import org.semanticdesktop.aperture.subcrawler.impl.SubCrawlerRegistryImpl; import org.semanticdesktop.aperture.test.subcrawler.SubCrawlerTestBase; import org.semanticdesktop.aperture.test.subcrawler.TestBasicSubCrawlerHandler; import org.semanticdesktop.aperture.util.DateUtil; +import org.semanticdesktop.aperture.util.IOUtil; +import org.semanticdesktop.aperture.util.ResourceUtil; import org.semanticdesktop.aperture.vocabulary.NCO; import org.semanticdesktop.aperture.vocabulary.NIE; @@ -61,6 +68,36 @@ metadata = null; } + public void testRfc2426ExampleExtractionMultiLevelMode() throws Exception { + /* + * With normal crawl, the two vcards are reported as normal file data objects + */ + VcardSubCrawler subCrawler = new VcardSubCrawler(true); + metadata = subCrawl(DOCS_PATH + "vcard-rfc2426.vcf", subCrawler, (SubCrawlerRegistry)null); + Model model = metadata.getModel(); + // we have ZERO here + assertStatementCount(0, model, Variable.ANY, RDF.type, NCO.PersonContact); + assertNewModUnmod(handler, 2, 0, 0); + metadata.dispose(); + + /* + * but with the subcrawler registry enabled, the same file is processed on + * two levels and the content is OK + */ + + SubCrawlerRegistry reg = new SubCrawlerRegistryImpl(); + reg.add(new VcardSubCrawlerFactory(true)); + + metadata = subCrawl(DOCS_PATH + "vcard-rfc2426.vcf", subCrawler, reg); + model = metadata.getModel(); + // we have TWO here (multi-level processing) + assertStatementCount(2, model, Variable.ANY, RDF.type, NCO.PersonContact); + assertNewModUnmod(handler, 2, 0, 0); + metadata.dispose(); + } + + + /** * The vcard-rfc2426.vcf contains more than one vcard, therefore the vcards inside will get a proper * vcard: uri. This test checks this. It uses an iterator because at the time of writing the jpim library @@ -278,11 +315,27 @@ metadata.dispose(); metadata = null; } + + public void testSapVcardsExtractionMultiLevelMode() throws Exception { + VcardSubCrawler subCrawler = new VcardSubCrawler(true); + metadata = subCrawl(DOCS_PATH + "vcard-vCards-SAP.vcf", subCrawler); + assertStatementCount(0, metadata.getModel(), Variable.ANY, RDF.type, NCO.PersonContact); + assertNewModUnmod(handler, 30, 0, 0); + metadata.dispose(); + + SubCrawlerRegistry reg = new SubCrawlerRegistryImpl(); + reg.add(new VcardSubCrawlerFactory(true)); + metadata = subCrawl(DOCS_PATH + "vcard-vCards-SAP.vcf", subCrawler, reg); + assertStatementCount(30, metadata.getModel(), Variable.ANY, RDF.type, NCO.PersonContact); + assertNewModUnmod(handler, 30, 0, 0); + metadata.dispose(); + + + } /** * The vcard-vCards-SAP.vcf contains more than one vcard, therefore the vcards inside will get a proper - * vcard: uri. This test checks this. It uses an iterator because at the time of writing the jpim library - * generated its own uids in a really crappy way that changed with each crawl. + * vcard: uri. This test checks this. * * @throws Exception */ @@ -292,6 +345,7 @@ Iterator<String> id = handler.getNewObjects().iterator(); for (int i = 0; i < 30; i++) { String st = id.next(); + System.out.println(st); assertTrue(st.startsWith("vcard:uri:dummyuri!/")); assertEquals(metadata.getDescribedUri(),findSingleObjectResource(metadata.getModel(), new URIImpl(st), NIE.isPartOf)); } @@ -299,6 +353,18 @@ metadata = null; } + public void testGetIndividualVcardInMultiLevelMode() throws Exception { + VcardSubCrawler subCrawler = new VcardSubCrawler(true); + DataObject ob = subCrawler.getDataObject(new URIImpl("uri:dummyuri"), "52787654178f112738459c0c29d155f244316ec4", + ResourceUtil.getInputStream(DOCS_PATH + "vcard-vCards-SAP.vcf", getClass()), null, null, null, new RDFContainerFactoryImpl()); + FileDataObject fdo = (FileDataObject)ob; + + byte [] vcardbytes = IOUtil.readBytes(fdo.getContent()); + byte [] expectedbytes = IOUtil.readBytes(ResourceUtil.getInputStream(DOCS_PATH + "vcard-vCards-SAP-markussprung.vcf", getClass())); + + assertTrue(Arrays.equals(expectedbytes, vcardbytes)); + } + /** * This case tests if the issue 2475980 is solved. Originally the vcard crawler used a library * called jpim which was crappy. Then we switched to ical4j-vcard which seems to be better. @@ -591,6 +657,14 @@ return parentMetadata; } + private RDFContainer subCrawl(String string, VcardSubCrawler subCrawler, SubCrawlerRegistry reg) throws Exception { + InputStream stream = org.semanticdesktop.aperture.util.ResourceUtil.getInputStream(string, this.getClass()); + handler = new TestBasicSubCrawlerHandler(reg); + RDFContainer parentMetadata = new RDFContainerImpl(handler.getModel(),new URIImpl("uri:dummyuri")); + subCrawler.subCrawl(null, stream, handler, null, null, null, null, parentMetadata); + return parentMetadata; + } + private void assertStatementCount(int count, Model model, ResourceOrVariable subject, UriOrVariable predicate, NodeOrVariable object) { int result = 0; ClosableIterator<? extends Statement> iter = null; @@ -606,7 +680,7 @@ assertEquals(count,result); } - public Resource findContact(Model model, String fullname) { + private Resource findContact(Model model, String fullname) { QueryResultTable table = model.sparqlSelect( "PREFIX nco: <" + NCO.NS_NCO + "> " + "SELECT ?contact " + Added: aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/util/ByteArrayCharSequenceTest.java =================================================================== --- aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/util/ByteArrayCharSequenceTest.java (rev 0) +++ aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/util/ByteArrayCharSequenceTest.java 2010-08-26 14:56:10 UTC (rev 2416) @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2010 Aduna and Deutsches Forschungszentrum fuer Kuenstliche Intelligenz DFKI GmbH. + * All rights reserved. + * + * Licensed under the Aperture BSD-Style license + */ +package org.semanticdesktop.aperture.util; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class ByteArrayCharSequenceTest { + + @Test + public void testSingleByteSequence() { + ByteArrayCharSequence s1 = new ByteArrayCharSequence( + new byte[] { 0x00 }); + assertEquals(1, s1.length()); + assertEquals('\u0000', s1.charAt(0)); + + ByteArrayCharSequence s2 = new ByteArrayCharSequence( + new byte[] { 0x7F }); + assertEquals(1, s2.length()); + assertEquals('\u007F', s2.charAt(0)); + + ByteArrayCharSequence s3 = new ByteArrayCharSequence( + new byte[] { (byte) 0xA0 }); + assertEquals(1, s3.length()); + assertEquals('\u00A0', s3.charAt(0)); + + ByteArrayCharSequence s4 = new ByteArrayCharSequence( + new byte[] { (byte) 0xFF }); + assertEquals(1, s4.length()); + assertEquals('\u00FF', s4.charAt(0)); + } + + @Test + public void testMultiByteSequence() { + { + ByteArrayCharSequence s1 = new ByteArrayCharSequence(new byte[] { + 0x00, 0x01, 0x03 }); + assertEquals(3, s1.length()); + assertEquals('\u0000', s1.charAt(0)); + assertEquals('\u0001', s1.charAt(1)); + assertEquals('\u0003', s1.charAt(2)); + assertEquals("\u0000\u0001\u0003", s1.toString()); + } + { + ByteArrayCharSequence s2 = new ByteArrayCharSequence(new byte[] { + 0x41, 0x6E, 0x74, 0x6F, 0x6E, 0x69 }); + assertEquals(6, s2.length()); + assertEquals('\u0041', s2.charAt(0)); + assertEquals('\u006E', s2.charAt(1)); + assertEquals('\u0074', s2.charAt(2)); + assertEquals('\u006F', s2.charAt(3)); + assertEquals('\u006E', s2.charAt(4)); + assertEquals('\u0069', s2.charAt(5)); + assertEquals("Antoni", s2.toString()); + } + } + + @Test + public void testSubSequence() { + ByteArrayCharSequence s2 = new ByteArrayCharSequence(new byte[] { 0x41, + 0x6E, 0x74, 0x6F, 0x6E, 0x69 }); + + { + CharSequence sub1 = s2.subSequence(0, 2); + assertEquals(2, sub1.length()); + assertEquals('\u0041', sub1.charAt(0)); + assertEquals('\u006E', sub1.charAt(1)); + } + { + CharSequence sub2 = s2.subSequence(3, 5); + assertEquals(2, sub2.length()); + assertEquals('\u006F', sub2.charAt(0)); + assertEquals('\u006E', sub2.charAt(1)); + } + { + CharSequence sub3 = s2.subSequence(1, 6); + assertEquals(5, sub3.length()); + assertEquals('\u006E', sub3.charAt(0)); + assertEquals('\u0074', sub3.charAt(1)); + assertEquals('\u006F', sub3.charAt(2)); + assertEquals('\u006E', sub3.charAt(3)); + assertEquals('\u0069', sub3.charAt(4)); + + CharSequence sub3_1 = sub3.subSequence(1, 5); + assertEquals(4, sub3_1.length()); + assertEquals('\u0074', sub3_1.charAt(0)); + assertEquals('\u006F', sub3_1.charAt(1)); + assertEquals('\u006E', sub3_1.charAt(2)); + assertEquals('\u0069', sub3_1.charAt(3)); + } + } + + @Test(expected=IndexOutOfBoundsException.class) + public void testToSmallIndex() { + ByteArrayCharSequence s2 = new ByteArrayCharSequence(new byte[] { 0x41,0x6E, 0x74, 0x6F, 0x6E, 0x69 }); + s2.charAt(-1); + } + + @Test(expected=IndexOutOfBoundsException.class) + public void testToLargeIndex() { + ByteArrayCharSequence s2 = new ByteArrayCharSequence(new byte[] { 0x41,0x6E, 0x74, 0x6F, 0x6E, 0x69 }); + s2.charAt(6); + } +} Property changes on: aperture/trunk/core/src/test/java/org/semanticdesktop/aperture/util/ByteArrayCharSequenceTest.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: aperture/trunk/core/src/test/resources/org/semanticdesktop/aperture/docs/vcard-vCards-SAP-markussprung.vcf =================================================================== --- aperture/trunk/core/src/test/resources/org/semanticdesktop/aperture/docs/vcard-vCards-SAP-markussprung.vcf (rev 0) +++ aperture/trunk/core/src/test/resources/org/semanticdesktop/aperture/docs/vcard-vCards-SAP-markussprung.vcf 2010-08-26 14:56:10 UTC (rev 2416) @@ -0,0 +1,9 @@ +BEGIN:VCARD +VERSION:3.0 +N:Sprung;Markus;;; +FN:Markus Sprung +ORG:SAP; +EMAIL;type=INTERNET;type=WORK;type=pref:Mar...@sa... +CATEGORIES:Demo,Nepomuk(SAP) +X-ABUID:8365FAAF-0362-4AF9-A080-D4DAED8BBF94\:ABPerson +END:VCARD This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |