Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PathExtraction initinal implementaion #1

Merged
merged 13 commits into from
Oct 18, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.gradle/
.idea/
build
gradle/
gradlew
gradlew.bat
out/
ion-c
84 changes: 84 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,90 @@

Ion Path Extraction API aims to combine the convenience of a DOM API with the speed of a streaming API.

The traditional streaming and DOM APIs force the user to choose between speed and convenience, respectively.
Path extraction APIs aim to combine the two by allowing the user to register paths into the data using just a
few lines of code and receive callbacks during stream processing when any of those paths is matched. This allows
the Ion reader to plan the most efficient traversal over the data without requiring further manual interaction
from the user. For example, there is no reason to step in to containers which could not possibly match one of
the search paths. When encoded in binary Ion, the resulting skip is a seek forward in the input stream, which
is inexpensive relative to the cost of parsing (and in the case of a DOM, materializing) the skipped value.

## Usage
Path extractor works in two phases:
1. Configuration
2. Notification

### Search Paths
A `SearchPath` is a path provided to the extractor for matching. It's composed of a list of `PathComponent`s
which can be one of:
* Wildcard: matches all values
* Index: match the value at that index
* Text: match all values whose field names are equivalent to that text

Some examples:
```
data on reader: {foo: ["foo1", "foo2"] , bar: "myBarValue"}

(foo 0) - matches "foo1"
(1) - matches "myBarValue"
(*) - matches ["foo1", "foo2"] and "myBarValue"
() - matches {foo: ["foo1", "foo2"] , bar: "myBarValue"}
```

### Configuration
The configuration phase involves building a `PathExtractor` instance through the `PathExtractorBuilder` by setting its
configuration options and registering its search paths. The built `PathExtractor` can be reused over many `IonReader`s.

example:

```java
PathExtractorBuilder.standard()
.withMatchCaseInsensitive(true)
.register("(foo)", (reader) -> { ... })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withSearchPath

.build()
```

see `PathExtractorBuilder` javadoc for more information on configuration options and search path registration.

### Notification
Each time the `PathExtractor` encounters a value that matches a registered search path it will invoke the respective
callback passing the reader positioned at the current value. See `PathExtractorBuilder#register` methods for more
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withSearchPath

information on the callback contract.

### Examples:

```java
// Capture all matched values into a List
final IonSystem ion = IonSystemBuilder.standard().build();

final List<IonValue> list = new ArrayList<>();
final Function<IonReader, Integer> callback = (reader) -> {
IonValue ionValue = ion.newValue(reader);
list.add(ionValue);

return 0;
};

final PathExtractor pathExtractor = PathExtractorBuilder.standard()
.register("(foo)", callback)
.register("(bar)", callback)
.register("(baz 1)", callback)
.build();

IonReader ionReader = ion.newReader("{foo: 1}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please help me teach users to use an IonReaderBuilder for constructing IonReaders. I dream of deprecating all of the miscellaneous non-DOM-related utility methods from IonSystem one day.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed. Also added a test for the example to avoid breaking in the future, which already happened...

+ "{bar: 2}"
+ "{baz: [10,20,30,40]}"
+ "{other: 99}"
);

pathExtractor.match(ionReader);

// list will contain 1, 2 and 20
```

## Ion Developer information
See the developer guide on: http://amzn.github.io/ion-docs/guides/path-extractor-guide.html

## License

This library is licensed under the Apache 2.0 License.
72 changes: 72 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at:
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file 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.
*/

buildscript {
ext.ionVersion = "1.2.+"
ext.kotlin_version = "1.2.+"
ext.junitVersion = "5.3.+"

repositories {
mavenCentral()
}

dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

apply plugin: "java"
apply plugin: "kotlin"

group 'software.amazon.ion'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
mavenCentral()
}

dependencies {
compile "software.amazon.ion:ion-java:$ionVersion"

// using kotlin to make tests less verbose
testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"

// JUnit 5
testCompile "org.junit.jupiter:junit-jupiter-api:$junitVersion"
testCompile "org.junit.jupiter:junit-jupiter-params:$junitVersion"
testRuntime "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = "1.8"
}
}

apply plugin: 'checkstyle'
checkstyle {
toolVersion = "8.12"
ignoreFailures = false
maxWarnings = 0
maxErrors = 0
configDir = file("$rootProject.projectDir/config/checkstyle")
}
tasks.withType(Checkstyle) {
reports {
xml.enabled = false
html.enabled = true
}
}
2 changes: 2 additions & 0 deletions config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Configuration
Project development configuration files, for example code style and checkstyle settings used on all modules
Loading