Author: rhauch
Date: 2009-06-04 17:42:27 -0400 (Thu, 04 Jun 2009)
New Revision: 975
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyType.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueComparators.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java
trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java
Log:
DNA-389 More minor corrections in how property types are determined for different values
(including values that are instances of non-canonical classes, such as Integer).
Discovered DNA-443, so adding temporary ignore to the sequencing test of Java source
code.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyType.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyType.java 2009-06-04
19:29:32 UTC (rev 974)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/PropertyType.java 2009-06-04
21:42:27 UTC (rev 975)
@@ -26,10 +26,13 @@
import java.math.BigDecimal;
import java.net.URI;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import java.util.UUID;
import net.jcip.annotations.Immutable;
import org.jboss.dna.common.util.CheckArg;
@@ -42,20 +45,45 @@
@Immutable
public enum PropertyType {
- STRING("String", ValueComparators.STRING_COMPARATOR, String.class),
- BINARY("Binary", ValueComparators.BINARY_COMPARATOR, Binary.class),
- LONG("Long", ValueComparators.LONG_COMPARATOR, Long.class),
- DOUBLE("Double", ValueComparators.DOUBLE_COMPARATOR, Double.class),
- DECIMAL("Decimal", ValueComparators.DECIMAL_COMPARATOR, BigDecimal.class),
- DATE("Date", ValueComparators.DATE_TIME_COMPARATOR, DateTime.class),
- BOOLEAN("Boolean", ValueComparators.BOOLEAN_COMPARATOR, Boolean.class),
- NAME("Name", ValueComparators.NAME_COMPARATOR, Name.class),
- PATH("Path", ValueComparators.PATH_COMPARATOR, Path.class),
- UUID("UUID", ValueComparators.UUID_COMPARATOR, UUID.class),
- REFERENCE("Reference", ValueComparators.REFERENCE_COMPARATOR,
Reference.class),
- URI("URI", ValueComparators.URI_COMPARATOR, URI.class),
- OBJECT("Object", ValueComparators.OBJECT_COMPARATOR, Object.class);
+ STRING("String", ValueComparators.STRING_COMPARATOR, new
ObjectCanonicalizer(), String.class),
+ BINARY("Binary", ValueComparators.BINARY_COMPARATOR, new
ObjectCanonicalizer(), Binary.class),
+ LONG("Long", ValueComparators.LONG_COMPARATOR, new LongCanonicalizer(),
Long.class, Integer.class, Short.class),
+ DOUBLE("Double", ValueComparators.DOUBLE_COMPARATOR, new
DoubleCanonicalizer(), Double.class, Float.class),
+ DECIMAL("Decimal", ValueComparators.DECIMAL_COMPARATOR, new
ObjectCanonicalizer(), BigDecimal.class),
+ DATE("Date", ValueComparators.DATE_TIME_COMPARATOR, new
ObjectCanonicalizer(), DateTime.class),
+ BOOLEAN("Boolean", ValueComparators.BOOLEAN_COMPARATOR, new
ObjectCanonicalizer(), Boolean.class),
+ NAME("Name", ValueComparators.NAME_COMPARATOR, new ObjectCanonicalizer(),
Name.class),
+ PATH("Path", ValueComparators.PATH_COMPARATOR, new ObjectCanonicalizer(),
Path.class),
+ UUID("UUID", ValueComparators.UUID_COMPARATOR, new ObjectCanonicalizer(),
UUID.class),
+ REFERENCE("Reference", ValueComparators.REFERENCE_COMPARATOR, new
ObjectCanonicalizer(), Reference.class),
+ URI("URI", ValueComparators.URI_COMPARATOR, new ObjectCanonicalizer(),
URI.class),
+ OBJECT("Object", ValueComparators.OBJECT_COMPARATOR, new
ObjectCanonicalizer(), Object.class);
+ private static interface Canonicalizer {
+ Object canonicalizeValue( Object value );
+ }
+
+ protected final static class ObjectCanonicalizer implements Canonicalizer {
+ public Object canonicalizeValue( Object value ) {
+ return value;
+ }
+ }
+
+ protected final static class LongCanonicalizer implements Canonicalizer {
+ public Object canonicalizeValue( Object value ) {
+ if (value instanceof Integer) return new Long((Integer)value);
+ if (value instanceof Short) return new Long((Short)value);
+ return value;
+ }
+ }
+
+ protected final static class DoubleCanonicalizer implements Canonicalizer {
+ public Object canonicalizeValue( Object value ) {
+ if (value instanceof Float) return new Double((Float)value);
+ return value;
+ }
+ }
+
private static final List<PropertyType> ALL_PROPERTY_TYPES;
static {
List<PropertyType> types = new ArrayList<PropertyType>();
@@ -67,14 +95,24 @@
private final String name;
private final Comparator<?> comparator;
+ private final Canonicalizer canonicalizer;
private final Class<?> valueClass;
+ private final Set<Class<?>> castableValueClasses;
private PropertyType( String name,
Comparator<?> comparator,
- Class<?> valueClass ) {
+ Canonicalizer canonicalizer,
+ Class<?> valueClass,
+ Class<?>... castableClasses ) {
this.name = name;
this.comparator = comparator;
+ this.canonicalizer = canonicalizer;
this.valueClass = valueClass;
+ if (castableClasses != null && castableClasses.length != 0) {
+ castableValueClasses = Collections.unmodifiableSet(new
HashSet<Class<?>>(Arrays.asList(castableClasses)));
+ } else {
+ castableValueClasses = Collections.emptySet();
+ }
}
public Class<?> getValueClass() {
@@ -89,21 +127,39 @@
return this.comparator;
}
- public boolean isTypeFor( Object value ) {
- return this.valueClass.isInstance(value);
+ /**
+ * Obtain a value of this type in its canonical form. Some property types allow
values to be instances of the canonical class
+ * or an alternative class. This method ensures that the value is always an instance
of the canonical class.
+ * <p>
+ * Note that this method does <i>not</i> cast from one property type to
another.
+ * </p>
+ *
+ * @param value the property value
+ * @return the value in canonical form
+ */
+ public Object getCanonicalValue( Object value ) {
+ return this.canonicalizer.canonicalizeValue(value);
}
- public boolean isTypeForEach( Iterable<?> values ) {
+ public final boolean isTypeFor( Object value ) {
+ if (this.valueClass.isInstance(value)) return true;
+ for (Class<?> valueClass : castableValueClasses) {
+ if (valueClass.isInstance(value)) return true;
+ }
+ return false;
+ }
+
+ public final boolean isTypeForEach( Iterable<?> values ) {
for (Object value : values) {
- if (!this.valueClass.isInstance(value)) return false;
+ if (!isTypeFor(value)) return false;
}
return true;
}
- public boolean isTypeForEach( Iterator<?> values ) {
+ public final boolean isTypeForEach( Iterator<?> values ) {
while (values.hasNext()) {
Object value = values.next();
- if (!this.valueClass.isInstance(value)) return false;
+ if (!isTypeFor(value)) return false;
}
return true;
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueComparators.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueComparators.java 2009-06-04
19:29:32 UTC (rev 974)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/ValueComparators.java 2009-06-04
21:42:27 UTC (rev 975)
@@ -308,6 +308,11 @@
if (o2 == null) return 1;
PropertyType type1 = PropertyType.discoverType(o1);
PropertyType type2 = PropertyType.discoverType(o2);
+
+ // Canonicalize the values ...
+ o1 = type1.getCanonicalValue(o1);
+ o2 = type2.getCanonicalValue(o2);
+
if (type1 != PropertyType.OBJECT && type2 != PropertyType.OBJECT) {
if (type1 == type2) return
((Comparator<Object>)type1.getComparator()).compare(o1, o2);
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java 2009-06-04
19:29:32 UTC (rev 974)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapter.java 2009-06-04
21:42:27 UTC (rev 975)
@@ -178,13 +178,18 @@
SequencerContext context ) {
PathFactory pathFactory =
context.getExecutionContext().getValueFactories().getPathFactory();
+ if (targetPath.isRoot()) return;
Path workingPath = pathFactory.createRootPath();
Path.Segment[] segments = targetPath.getSegmentsArray();
- for (int i = 0; i < segments.length; i++) {
- workingPath = pathFactory.create(workingPath, segments[i]);
-
- context.graph().createIfMissing(workingPath);
+ int i = 0;
+ if (segments.length > 1) {
+ for (int max = segments.length - 1; i < max; i++) {
+ workingPath = pathFactory.create(workingPath, segments[i]);
+ context.graph().createIfMissing(workingPath);
+ }
}
+ workingPath = pathFactory.create(workingPath, segments[i]);
+ context.graph().create(workingPath);
}
/**
Modified:
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java
===================================================================
---
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java 2009-06-04
19:29:32 UTC (rev 974)
+++
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencer/SequencingClient.java 2009-06-04
21:42:27 UTC (rev 975)
@@ -103,9 +103,9 @@
config.sequencer("Java Sequencer")
.usingClass("org.jboss.dna.sequencer.java.JavaMetadataSequencer")
.loadedFromClasspath()
- .setDescription("Sequences mp3 files to extract the id3 tags of the
audio file")
- .sequencingFrom("//(*.mp3[*])/jcr:content[@jcr:data]")
- .andOutputtingTo("/mp3s/$1");
+ .setDescription("Sequences Java files to extract the AST structure of
the Java source code")
+ .sequencingFrom("//(*.java[*])/jcr:content[@jcr:data]")
+ .andOutputtingTo("/java/$1");
// Now start the client and tell it which repository and workspace to use ...
SequencingClient client = new SequencingClient(config, repositoryId,
workspaceName);
Modified:
trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java
===================================================================
---
trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java 2009-06-04
19:29:32 UTC (rev 974)
+++
trunk/docs/examples/gettingstarted/sequencers/src/test/java/org/jboss/example/dna/sequencer/SequencingClientTest.java 2009-06-04
21:42:27 UTC (rev 975)
@@ -26,6 +26,7 @@
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
@@ -91,9 +92,9 @@
// Set up the Java source file sequencer ...
config.sequencer("Java Sequencer")
.usingClass(JavaMetadataSequencer.class)
- .setDescription("Sequences mp3 files to extract the id3 tags of the
audio file")
- .sequencingFrom("//(*.mp3[*])/jcr:content[@jcr:data]")
- .andOutputtingTo("/mp3s/$1");
+ .setDescription("Sequences Java files to extract the AST structure of
the Java source code")
+ .sequencingFrom("//(*.java[*])/jcr:content[@jcr:data]")
+ .andOutputtingTo("/java/$1");
// Now start the client and tell it which repository and workspace to use ...
client = new SequencingClient(config, repositoryId, workspaceName);
@@ -125,69 +126,64 @@
client.startRepository();
client.uploadFile();
- // Use a trick to wait until the sequencing has been done by sleeping (to give
the sequencing time to start)
- // and to then shut down the DNA services (which will block until all sequencing
has been completed) ...
- Thread.sleep(4000);
+ waitUntilSequencedNodesIs(1);
- assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
-
// The sequencers should have run, so perform the search.
// The mock user interface checks the results.
client.search();
}
- @Ignore
@Test
public void shouldUploadAndSequenceJpegFile() throws Exception {
client.setUserInterface(new MockUserInterface(this.jpegImageUrl,
"/a/b/caution.jpeg", 1));
client.startRepository();
client.uploadFile();
- // Use a trick to wait until the sequencing has been done by sleeping (to give
the sequencing time to start)
- // and to then shut down the DNA services (which will block until all sequencing
has been completed) ...
- Thread.sleep(1000);
+ waitUntilSequencedNodesIs(1);
// The sequencers should have run, so perform the search.
// The mock user interface checks the results.
client.search();
-
- assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
}
- @Ignore
@Test
- public void shouldUploadAndNotSequencePictFile() throws Exception {
- client.setUserInterface(new MockUserInterface(this.pictImageUrl,
"/a/b/caution.pict", 0));
+ public void shouldUploadAndSequenceMp3File() throws Exception {
+ client.setUserInterface(new MockUserInterface(this.mp3Url,
"/a/b/test.mp3", 1));
client.startRepository();
client.uploadFile();
- // Use a trick to wait until the sequencing has been done by sleeping (to give
the sequencing time to start)
- // and to then shut down the DNA services (which will block until all sequencing
has been completed) ...
- Thread.sleep(1000);
+ waitUntilSequencedNodesIs(1);
// The sequencers should have run, so perform the search.
// The mock user interface checks the results.
client.search();
-
- assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(0l));
}
@Ignore
@Test
- public void shouldUploadAndSequenceMp3File() throws Exception {
- client.setUserInterface(new MockUserInterface(this.mp3Url,
"/a/b/test.mp3", 1));
+ public void shouldUploadAndSequenceJavaSourceFile() throws Exception {
+ client.setUserInterface(new MockUserInterface(this.javaSourceUrl,
"/a/b/MySource.java", 1));
client.startRepository();
client.uploadFile();
- // Use a trick to wait until the sequencing has been done by sleeping (to give
the sequencing time to start)
- // and to then shut down the DNA services (which will block until all sequencing
has been completed) ...
- Thread.sleep(1000);
+ waitUntilSequencedNodesIs(1);
// The sequencers should have run, so perform the search.
// The mock user interface checks the results.
client.search();
+ }
- assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1l));
+ protected void waitUntilSequencedNodesIs( int totalNumberOfNodesSequenced ) throws
InterruptedException {
+ // check 50 times, waiting 0.1 seconds between (for a total of 5 seconds max)
...
+ long numFound = 0;
+ for (int i = 0; i != 50; i++) {
+ numFound = client.getStatistics().getNumberOfNodesSequenced();
+ if (numFound >= totalNumberOfNodesSequenced) {
+ return;
+ }
+ Thread.sleep(100);
+ }
+ fail("Expected to find " + totalNumberOfNodesSequenced + " nodes
sequenced, but found " + numFound);
}
@Test
@@ -203,21 +199,4 @@
}
}
- @Ignore
- @Test
- public void shouldUploadAndSequenceJavaSourceFile() throws Exception {
- client.setUserInterface(new MockUserInterface(this.javaSourceUrl,
"/a/b/MySource.java", 1));
- client.startRepository();
- client.uploadFile();
-
- // Use a trick to wait until the sequencing has been done by sleeping (to give
the sequencing time to start)
- // and to then shut down the DNA services (which will block until all sequencing
has been completed) ...
- Thread.sleep(1000);
-
- // The sequencers should have run, so perform the search.
- // The mock user interface checks the results.
- client.search();
- assertThat(client.getStatistics().getNumberOfNodesSequenced(), is(1L));
- }
-
}