http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/pom.xml b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/pom.xml new file mode 100644 index 0000000..d7d5605 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/pom.xml @@ -0,0 +1,31 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <!-- + 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. + --> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-standard-services</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>nifi-record-serialization-service-api</artifactId> + <packaging>jar</packaging> + <dependencies> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-api</artifactId> + </dependency> + </dependencies> +</project>
http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/DataTypeValidator.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/DataTypeValidator.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/DataTypeValidator.java new file mode 100644 index 0000000..5a71086 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/DataTypeValidator.java @@ -0,0 +1,82 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.nifi.components.ValidationContext; +import org.apache.nifi.components.ValidationResult; +import org.apache.nifi.components.Validator; + +public class DataTypeValidator implements Validator { + private static final Set<String> validValues; + private static final Set<String> allowsFormatting; + + static { + final Set<String> values = new HashSet<>(); + values.add("string"); + values.add("boolean"); + values.add("byte"); + values.add("char"); + values.add("int"); + values.add("long"); + values.add("float"); + values.add("double"); + values.add("time"); + values.add("date"); + values.add("timestamp"); + validValues = Collections.unmodifiableSet(values); + + final Set<String> formattable = new HashSet<>(); + formattable.add("date"); + formattable.add("time"); + formattable.add("timestmap"); + allowsFormatting = Collections.unmodifiableSet(formattable); + } + + @Override + public ValidationResult validate(final String subject, final String input, final ValidationContext context) { + final String[] splits = input.split("\\:"); + + final boolean valid; + if (splits.length == 2) { + final String type = splits[0].trim(); + if (validValues.contains(type)) { + if (allowsFormatting.contains(splits[0].trim())) { + valid = true; + } else { + valid = false; + } + } else { + valid = false; + } + } else { + valid = validValues.contains(input.trim()); + } + + return new ValidationResult.Builder() + .subject(subject) + .input(input) + .valid(valid) + .explanation("Valid values for this property are: " + validValues + + ", where date, time, and timestamp may optionally contain a format (e.g., date:MM-dd-yyyy)") + .build(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/MalformedRecordException.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/MalformedRecordException.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/MalformedRecordException.java new file mode 100644 index 0000000..d45a850 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/MalformedRecordException.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +/** + * An Exception that can be thrown to indicate that data was read but could not properly be parsed + */ +public class MalformedRecordException extends Exception { + public MalformedRecordException(final String message) { + super(message); + } + + public MalformedRecordException(final String message, final Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordReader.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordReader.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordReader.java new file mode 100644 index 0000000..a0cfc79 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordReader.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +import java.io.Closeable; +import java.io.IOException; + +import org.apache.nifi.serialization.record.Record; +import org.apache.nifi.serialization.record.RecordSchema; + +/** + * <p> + * A RowRecordReader is responsible for parsing data and returning a record at a time + * in order to allow the caller to iterate over the records individually. + * </p> + * + * <p> + * PLEASE NOTE: This interface is still considered 'unstable' and may change in a non-backward-compatible + * manner between minor or incremental releases of NiFi. + * </p> + */ +public interface RecordReader extends Closeable { + + /** + * Returns the next record in the stream or <code>null</code> if no more records are available. + * + * @param schema the schema to use in order to determine how to interprets the fields in a record + * @return the next record in the stream or <code>null</code> if no more records are available. + * + * @throws IOException if unable to read from the underlying data + * @throws MalformedRecordException if an unrecoverable failure occurs when trying to parse a record + */ + Record nextRecord() throws IOException, MalformedRecordException; + + /** + * @return a RecordSchema that is appropriate for the records in the stream + * @throws MalformedRecordException if an unrecoverable failure occurs when trying to parse the underlying data + */ + RecordSchema getSchema() throws MalformedRecordException; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriter.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriter.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriter.java new file mode 100644 index 0000000..7d6fa1c --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriter.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.nifi.serialization.record.RecordSet; + +/** + * <p> + * A ResultSetWriter is responsible for writing a ResultSet to a given {@link OutputStream}. + * </p> + * + * <p> + * PLEASE NOTE: This interface is still considered 'unstable' and may change in a non-backward-compatible + * manner between minor or incremental releases of NiFi. + * </p> + */ +public interface RecordSetWriter extends RecordWriter { + /** + * Writes the given result set to the given output stream + * + * @param recordSet the record set to serialize + * @param out the OutputStream to write to + * @return the results of writing the data + * @throws IOException if unable to write to the given OutputStream + */ + WriteResult write(RecordSet recordSet, OutputStream out) throws IOException; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriterFactory.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriterFactory.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriterFactory.java new file mode 100644 index 0000000..2286f3f --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordSetWriterFactory.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.logging.ComponentLog; + +/** + * <p> + * A Controller Service that is responsible for creating a {@link RecordSetWriter}. + * </p> + */ +public interface RecordSetWriterFactory extends ControllerService { + RecordSetWriter createWriter(ComponentLog logger); +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordWriter.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordWriter.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordWriter.java new file mode 100644 index 0000000..eef8d82 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RecordWriter.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.nifi.serialization.record.Record; + +public interface RecordWriter { + /** + * Writes the given result set to the given output stream + * + * @param recordSet the record set to serialize + * @param out the OutputStream to write to + * @return the results of writing the data + * @throws IOException if unable to write to the given OutputStream + */ + WriteResult write(Record record, OutputStream out) throws IOException; + + /** + * @return the MIME Type that the Result Set Writer produces. This will be added to FlowFiles using + * the mime.type attribute. + */ + String getMimeType(); +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RowRecordReaderFactory.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RowRecordReaderFactory.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RowRecordReaderFactory.java new file mode 100644 index 0000000..5ef4c7c --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/RowRecordReaderFactory.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.logging.ComponentLog; + +/** + * <p> + * A Controller Service that is responsible for creating a {@link RecordReader}. + * </p> + */ +public interface RowRecordReaderFactory extends ControllerService { + RecordReader createRecordReader(InputStream in, ComponentLog logger) throws MalformedRecordException, IOException; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/SimpleRecordSchema.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/SimpleRecordSchema.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/SimpleRecordSchema.java new file mode 100644 index 0000000..246e0af --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/SimpleRecordSchema.java @@ -0,0 +1,126 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.stream.Collectors; + +import org.apache.nifi.serialization.record.DataType; +import org.apache.nifi.serialization.record.RecordField; +import org.apache.nifi.serialization.record.RecordSchema; + +public class SimpleRecordSchema implements RecordSchema { + private final List<RecordField> fields; + private final Map<String, Integer> fieldIndices; + + public SimpleRecordSchema(final List<RecordField> fields) { + this.fields = Collections.unmodifiableList(new ArrayList<>(fields)); + this.fieldIndices = new HashMap<>(fields.size()); + + int index = 0; + for (final RecordField field : fields) { + fieldIndices.put(field.getFieldName(), index++); + } + } + + @Override + public List<RecordField> getFields() { + return fields; + } + + @Override + public int getFieldCount() { + return fields.size(); + } + + @Override + public RecordField getField(final int index) { + return fields.get(index); + } + + @Override + public List<DataType> getDataTypes() { + return getFields().stream().map(recordField -> recordField.getDataType()) + .collect(Collectors.toList()); + } + + @Override + public List<String> getFieldNames() { + return getFields().stream().map(recordField -> recordField.getFieldName()) + .collect(Collectors.toList()); + } + + @Override + public Optional<DataType> getDataType(final String fieldName) { + final OptionalInt idx = getFieldIndex(fieldName); + return idx.isPresent() ? Optional.of(fields.get(idx.getAsInt()).getDataType()) : Optional.empty(); + } + + private OptionalInt getFieldIndex(final String fieldName) { + final Integer index = fieldIndices.get(fieldName); + return index == null ? OptionalInt.empty() : OptionalInt.of(index); + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (!(obj instanceof RecordSchema)) { + return false; + } + + final RecordSchema other = (RecordSchema) obj; + return fields.equals(other.getFields()); + } + + @Override + public int hashCode() { + return 143 + 3 * fields.hashCode(); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("["); + + for (int i = 0; i < fields.size(); i++) { + final RecordField field = fields.get(i); + + sb.append("\""); + sb.append(field.getFieldName()); + sb.append("\" : \""); + sb.append(field.getDataType()); + sb.append("\""); + + if (i < fields.size() - 1) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/WriteResult.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/WriteResult.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/WriteResult.java new file mode 100644 index 0000000..3fb2741 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/WriteResult.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization; + +import java.util.Collections; +import java.util.Map; + +/** + * <p> + * Provides information about what was written to an OutputStream by a {@link RecordSetWriter}. + * Instances of WriteResult are typically instantiated by calling the static method {@link WriteResult#of(int, Map)} + * or using {@link WriteResult#EMPTY}. + * </p> + * + * <p> + * PLEASE NOTE: This interface is still considered 'unstable' and may change in a non-backward-compatible + * manner between minor or incremental releases of NiFi. + * </p> + */ +public interface WriteResult { + + /** + * @return the number of records written + */ + int getRecordCount(); + + /** + * @return values that should be added to the FlowFile as attributes + */ + Map<String, String> getAttributes(); + + /** + * Creates a WriteResult with the given record count and attributes + * + * @param recordCount the number of records written + * @param attributes the attributes to add to the FlowFile + * @return A {@link WriteResult} representing the given parameters + */ + public static WriteResult of(final int recordCount, final Map<String, String> attributes) { + return new WriteResult() { + @Override + public int getRecordCount() { + return recordCount; + } + + @Override + public Map<String, String> getAttributes() { + return attributes; + } + }; + } + + public static final WriteResult EMPTY = of(0, Collections.emptyMap()); +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/DataType.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/DataType.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/DataType.java new file mode 100644 index 0000000..0c187f1 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/DataType.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +public class DataType { + private final RecordFieldType fieldType; + private final String format; + + private final RecordSchema childSchema; + private final List<DataType> childTypes; + + DataType(final RecordFieldType fieldType, final String format) { + this(fieldType, format, (RecordSchema) null); + } + + DataType(final RecordFieldType fieldType, final String format, final RecordSchema childSchema) { + this.fieldType = fieldType; + this.format = format; + this.childSchema = childSchema; + this.childTypes = Collections.emptyList(); + } + + DataType(final RecordFieldType fieldType, final String format, final List<DataType> childTypes) { + this.fieldType = fieldType; + this.format = format; + this.childSchema = null; + this.childTypes = Collections.unmodifiableList(childTypes); + } + + + public String getFormat() { + return format; + } + + public RecordFieldType getFieldType() { + return fieldType; + } + + public Optional<RecordSchema> getChildRecordSchema() { + return Optional.ofNullable(childSchema); + } + + public List<DataType> getPossibleTypes() { + return childTypes; + } + + @Override + public int hashCode() { + return 31 + 41 * fieldType.hashCode() + 41 * (format == null ? 0 : format.hashCode()); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof DataType)) { + return false; + } + + final DataType other = (DataType) obj; + return fieldType.equals(other.fieldType) && ((format == null && other.format == null) || (format != null && format.equals(other.format))); + } + + @Override + public String toString() { + if (format == null) { + return fieldType.toString(); + } else { + return fieldType.toString() + ":" + format; + } + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ListRecordSet.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ListRecordSet.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ListRecordSet.java new file mode 100644 index 0000000..3968f50 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ListRecordSet.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ListRecordSet implements RecordSet { + private final Iterator<Record> recordItr; + private final RecordSchema schema; + + public ListRecordSet(final RecordSchema schema, final List<Record> records) { + this.schema = schema; + + final List<Record> copy = new ArrayList<>(records); + recordItr = copy.iterator(); + } + + @Override + public RecordSchema getSchema() { + return schema; + } + + @Override + public Record next() { + return recordItr.hasNext() ? recordItr.next() : null; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/MapRecord.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/MapRecord.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/MapRecord.java new file mode 100644 index 0000000..f3f9024 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/MapRecord.java @@ -0,0 +1,322 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +import java.sql.Time; +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public class MapRecord implements Record { + private final RecordSchema schema; + private final Map<String, Object> values; + + public MapRecord(final RecordSchema schema, final Map<String, Object> values) { + this.schema = Objects.requireNonNull(schema); + this.values = Objects.requireNonNull(values); + } + + @Override + public RecordSchema getSchema() { + return schema; + } + + @Override + public Object[] getValues() { + final Object[] values = new Object[schema.getFieldCount()]; + int i = 0; + for (final String fieldName : schema.getFieldNames()) { + values[i++] = getValue(fieldName); + } + return values; + } + + @Override + public Object getValue(final String fieldName) { + return values.get(fieldName); + } + + @Override + public String getAsString(final String fieldName) { + final Optional<DataType> dataTypeOption = schema.getDataType(fieldName); + if (!dataTypeOption.isPresent()) { + return null; + } + + return convertToString(getValue(fieldName), dataTypeOption.get().getFormat()); + } + + @Override + public String getAsString(final String fieldName, final String format) { + return convertToString(getValue(fieldName), format); + } + + private String getFormat(final String optionalFormat, final RecordFieldType fieldType) { + return (optionalFormat == null) ? fieldType.getDefaultFormat() : optionalFormat; + } + + private String convertToString(final Object value, final String format) { + if (value == null) { + return null; + } + + if (value instanceof java.sql.Date) { + java.sql.Date date = (java.sql.Date) value; + final long time = date.getTime(); + return new SimpleDateFormat(getFormat(format, RecordFieldType.DATE)).format(new java.util.Date(time)); + } + if (value instanceof java.util.Date) { + return new SimpleDateFormat(getFormat(format, RecordFieldType.DATE)).format((java.util.Date) value); + } + if (value instanceof Timestamp) { + java.sql.Timestamp date = (java.sql.Timestamp) value; + final long time = date.getTime(); + return new SimpleDateFormat(getFormat(format, RecordFieldType.TIMESTAMP)).format(new java.util.Date(time)); + } + if (value instanceof Time) { + java.sql.Time date = (java.sql.Time) value; + final long time = date.getTime(); + return new SimpleDateFormat(getFormat(format, RecordFieldType.TIME)).format(new java.util.Date(time)); + } + + return value.toString(); + } + + @Override + public Long getAsLong(final String fieldName) { + return convertToLong(getValue(fieldName), fieldName); + } + + private Long convertToLong(final Object value, final Object fieldDesc) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).longValue(); + } + if (value instanceof String) { + return Long.parseLong((String) value); + } + if (value instanceof Date) { + return ((Date) value).getTime(); + } + + throw new TypeMismatchException("Cannot convert value of type " + value.getClass() + " to Long for field " + fieldDesc); + } + + @Override + public Integer getAsInt(final String fieldName) { + return convertToInt(getValue(fieldName), fieldName); + } + + private Integer convertToInt(final Object value, final Object fieldDesc) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).intValue(); + } + if (value instanceof String) { + return Integer.parseInt((String) value); + } + + throw new TypeMismatchException("Cannot convert value of type " + value.getClass() + " to Integer for field " + fieldDesc); + } + + + @Override + public Double getAsDouble(final String fieldName) { + return convertToDouble(getValue(fieldName), fieldName); + } + + private Double convertToDouble(final Object value, final Object fieldDesc) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + if (value instanceof String) { + return Double.parseDouble((String) value); + } + + throw new TypeMismatchException("Cannot convert value of type " + value.getClass() + " to Double for field " + fieldDesc); + } + + @Override + public Float getAsFloat(final String fieldName) { + return convertToFloat(getValue(fieldName), fieldName); + } + + private Float convertToFloat(final Object value, final Object fieldDesc) { + if (value == null) { + return null; + } + + if (value instanceof Number) { + return ((Number) value).floatValue(); + } + if (value instanceof String) { + return Float.parseFloat((String) value); + } + + throw new TypeMismatchException("Cannot convert value of type " + value.getClass() + " to Float for field " + fieldDesc); + } + + @Override + public Record getAsRecord(String fieldName) { + return convertToRecord(getValue(fieldName), fieldName); + } + + private Record convertToRecord(final Object value, final Object fieldDesc) { + if (value == null) { + return null; + } + + if (value instanceof Record) { + return (Record) value; + } + + throw new TypeMismatchException("Cannot convert value of type " + value.getClass() + " to Record for field " + fieldDesc); + } + + + @Override + public Boolean getAsBoolean(final String fieldName) { + return convertToBoolean(getValue(fieldName), fieldName); + } + + private Boolean convertToBoolean(final Object value, final Object fieldDesc) { + if (value == null) { + return null; + } + + if (value instanceof Boolean) { + return (Boolean) value; + } + if (value instanceof String) { + final String string = (String) value; + if (string.equalsIgnoreCase("true") || string.equalsIgnoreCase("t")) { + return Boolean.TRUE; + } + + if (string.equalsIgnoreCase("false") || string.equals("f")) { + return Boolean.FALSE; + } + + throw new TypeMismatchException("Cannot convert String value to Boolean for field " + fieldDesc + " because it is not a valid boolean value"); + } + + throw new TypeMismatchException("Cannot convert value of type " + value.getClass() + " to Boolean for field " + fieldDesc); + } + + @Override + public Date getAsDate(final String fieldName) { + final Optional<DataType> dataTypeOption = schema.getDataType(fieldName); + if (!dataTypeOption.isPresent()) { + return null; + } + + return convertToDate(getValue(fieldName), fieldName, dataTypeOption.get().getFormat()); + } + + @Override + public Date getAsDate(final String fieldName, final String format) { + return convertToDate(getValue(fieldName), fieldName, format); + } + + private Date convertToDate(final Object value, final Object fieldDesc, final String format) { + if (value == null) { + return null; + } + + if (value instanceof Date) { + return (Date) value; + } + if (value instanceof Number) { + final Long time = ((Number) value).longValue(); + return new Date(time); + } + if (value instanceof java.sql.Date) { + return new Date(((java.sql.Date) value).getTime()); + } + if (value instanceof String) { + try { + return new SimpleDateFormat(getFormat(format, RecordFieldType.DATE)).parse((String) value); + } catch (final ParseException e) { + throw new TypeMismatchException("Cannot convert String value to date for field " + fieldDesc + " because it is not in the correct format of: " + format, e); + } + } + + throw new TypeMismatchException("Cannot convert value of type " + value.getClass() + " to Boolean for field " + fieldDesc); + } + + @Override + public Object[] getAsArray(final String fieldName) { + return convertToArray(getValue(fieldName)); + } + + private Object[] convertToArray(final Object value) { + if (value == null) { + return null; + } + + if (value instanceof Object[]) { + return (Object[]) value; + } + + if (value instanceof List) { + return ((List<?>) value).toArray(); + } + + return new Object[] {value}; + } + + @Override + public int hashCode() { + return 31 + 41 * values.hashCode() + 7 * schema.hashCode(); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof MapRecord)) { + return false; + } + final MapRecord other = (MapRecord) obj; + return schema.equals(other.schema) && values.equals(other.values); + } + + @Override + public String toString() { + return "MapRecord[values=" + values + "]"; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/Record.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/Record.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/Record.java new file mode 100644 index 0000000..ca85741 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/Record.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +import java.util.Date; + +public interface Record { + + RecordSchema getSchema(); + + /** + * <p> + * Returns a view of the the values of the fields in this Record. + * </p> + * + * <b>NOTE:</b> The array that is returned may be an underlying array that is backing + * the contents of the Record. As such, modifying the array in any way may result in + * modifying the record. + * + * @return a view of the values of the fields in this Record + */ + Object[] getValues(); + + Object getValue(String fieldName); + + String getAsString(String fieldName); + + String getAsString(String fieldName, String format); + + Long getAsLong(String fieldName); + + Integer getAsInt(String fieldName); + + Double getAsDouble(String fieldName); + + Float getAsFloat(String fieldName); + + Record getAsRecord(String fieldName); + + Boolean getAsBoolean(String fieldName); + + Date getAsDate(String fieldName); + + Date getAsDate(String fieldName, String format); + + Object[] getAsArray(String fieldName); +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordField.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordField.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordField.java new file mode 100644 index 0000000..135ae66 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordField.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +public class RecordField { + private final String fieldName; + private final DataType dataType; + + public RecordField(final String fieldName, final DataType dataType) { + this.fieldName = fieldName; + this.dataType = dataType; + } + + public String getFieldName() { + return fieldName; + } + + public DataType getDataType() { + return dataType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((dataType == null) ? 0 : dataType.hashCode()); + result = prime * result + ((fieldName == null) ? 0 : fieldName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + + if (getClass() != obj.getClass()) { + return false; + } + + RecordField other = (RecordField) obj; + return dataType.equals(other.getDataType()) && fieldName.equals(other.getFieldName()); + } + + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordFieldType.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordFieldType.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordFieldType.java new file mode 100644 index 0000000..8ad212b --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordFieldType.java @@ -0,0 +1,114 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public enum RecordFieldType { + STRING("string"), + BOOLEAN("boolean"), + BYTE("byte"), + CHAR("char"), + SHORT("short"), + INT("int"), + BIGINT("bigint"), + LONG("long"), + FLOAT("float"), + DOUBLE("double"), + DATE("date", "yyyy-MM-dd"), + TIME("time", "HH:mm:ss"), + TIMESTAMP("timestamp", "yyyy-MM-dd HH:mm:ss"), + RECORD("record"), + CHOICE("choice"), + ARRAY("array"); + + + private static final Map<String, RecordFieldType> SIMPLE_NAME_MAP = new HashMap<String, RecordFieldType>(); + + static { + for (RecordFieldType value : values()) { + SIMPLE_NAME_MAP.put(value.simpleName, value); + } + } + + private final String simpleName; + private final String defaultFormat; + private final DataType defaultDataType; + + private RecordFieldType(final String simpleName) { + this(simpleName, null); + } + + private RecordFieldType(final String simpleName, final String defaultFormat) { + this.simpleName = simpleName; + this.defaultFormat = defaultFormat; + this.defaultDataType = new DataType(this, defaultFormat); + } + + public String getDefaultFormat() { + return defaultFormat; + } + + /** + * @return the DataType with the default format + */ + public DataType getDataType() { + return defaultDataType; + } + + public DataType getDataType(final String format) { + return new DataType(this, format); + } + + /** + * Returns a Data Type that represents a "RECORD" type with the given schema. + * + * @param childSchema the Schema for the Record + * @return a DataType that represents a Record with the given schema, or <code>null</code> if this RecordFieldType + * is not the RECORD type. + */ + public DataType getDataType(final RecordSchema childSchema) { + if (this != RECORD) { + return null; + } + + return new DataType(this, getDefaultFormat(), childSchema); + } + + /** + * Returns a Data Type that represents a "CHOICE" of multiple possible types. This method is + * only applicable for a RecordFieldType of {@link #CHOICE}. + * + * @param possibleChildTypes the possible types that are allowable + * @return a DataType that represents a "CHOICE" of multiple possible types, or <code>null</code> if this RecordFieldType + * is not the CHOICE type. + */ + public DataType getDataType(final List<DataType> possibleChildTypes) { + if (this != CHOICE) { + return null; + } + + return new DataType(this, getDefaultFormat(), possibleChildTypes); + } + + public static RecordFieldType of(final String typeString) { + return SIMPLE_NAME_MAP.get(typeString); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSchema.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSchema.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSchema.java new file mode 100644 index 0000000..115fb51 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSchema.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +import java.util.List; +import java.util.Optional; + +public interface RecordSchema { + /** + * @return the list of fields that are present in the schema + */ + List<RecordField> getFields(); + + /** + * @return the number of fields in the schema + */ + int getFieldCount(); + + /** + * @param index the 0-based index of which field to return + * @return the index'th field + * + * @throws IndexOutOfBoundsException if the index is < 0 or >= the number of fields (determined by {@link #getFieldCount()}). + */ + RecordField getField(int index); + + /** + * @return the data types of the fields + */ + List<DataType> getDataTypes(); + + /** + * @return the names of the fields + */ + List<String> getFieldNames(); + + /** + * @param fieldName the name of the field whose type is desired + * @return the RecordFieldType associated with the field that has the given name, or + * <code>null</code> if the schema does not contain a field with the given name + */ + Optional<DataType> getDataType(String fieldName); +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSet.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSet.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSet.java new file mode 100644 index 0000000..25bbcdc --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/RecordSet.java @@ -0,0 +1,53 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +import java.io.IOException; + +public interface RecordSet { + + /** + * @return the {@link RecordSchema} that applies to the records in this RecordSet + */ + RecordSchema getSchema() throws IOException; + + /** + * @return the next {@link Record} in the set or <code>null</code> if there are no more records + */ + Record next() throws IOException; + + public static RecordSet of(final RecordSchema schema, final Record... records) { + return new RecordSet() { + private int index = 0; + + @Override + public RecordSchema getSchema() { + return schema; + } + + @Override + public Record next() { + if (index >= records.length) { + return null; + } + + return records[index++]; + } + }; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java new file mode 100644 index 0000000..e166918 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/ResultSetRecordSet.java @@ -0,0 +1,169 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +import java.io.Closeable; +import java.io.IOException; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Types; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.nifi.serialization.SimpleRecordSchema; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ResultSetRecordSet implements RecordSet, Closeable { + private static final Logger logger = LoggerFactory.getLogger(ResultSetRecordSet.class); + private final ResultSet rs; + private final RecordSchema schema; + private final Set<String> rsColumnNames; + + public ResultSetRecordSet(final ResultSet rs) throws SQLException { + this.rs = rs; + this.schema = createSchema(rs); + + rsColumnNames = new HashSet<>(); + final ResultSetMetaData metadata = rs.getMetaData(); + for (int i = 0; i < metadata.getColumnCount(); i++) { + rsColumnNames.add(metadata.getColumnLabel(i + 1)); + } + } + + @Override + public RecordSchema getSchema() { + return schema; + } + + @Override + public Record next() throws IOException { + try { + if (rs.next()) { + return createRecord(rs); + } + } catch (final SQLException e) { + throw new IOException("Could not obtain next record from ResultSet", e); + } + + return null; + } + + @Override + public void close() { + try { + rs.close(); + } catch (final SQLException e) { + logger.error("Failed to close ResultSet", e); + } + } + + private Record createRecord(final ResultSet rs) throws SQLException { + final Map<String, Object> values = new HashMap<>(schema.getFieldCount()); + + for (final RecordField field : schema.getFields()) { + final String fieldName = field.getFieldName(); + + final Object value; + if (rsColumnNames.contains(fieldName)) { + value = rs.getObject(field.getFieldName()); + } else { + value = null; + } + + values.put(fieldName, value); + } + + return new MapRecord(schema, values); + } + + private static RecordSchema createSchema(final ResultSet rs) throws SQLException { + final ResultSetMetaData metadata = rs.getMetaData(); + final int numCols = metadata.getColumnCount(); + final List<RecordField> fields = new ArrayList<>(numCols); + + for (int i = 0; i < numCols; i++) { + final int column = i + 1; + final int sqlType = metadata.getColumnType(column); + + final RecordFieldType fieldType = getFieldType(sqlType); + final String fieldName = metadata.getColumnLabel(column); + final RecordField field = new RecordField(fieldName, fieldType.getDataType()); + fields.add(field); + } + + return new SimpleRecordSchema(fields); + } + + private static RecordFieldType getFieldType(final int sqlType) { + switch (sqlType) { + case Types.ARRAY: + return RecordFieldType.ARRAY; + case Types.BIGINT: + case Types.ROWID: + return RecordFieldType.LONG; + case Types.BINARY: + case Types.LONGVARBINARY: + case Types.VARBINARY: + return RecordFieldType.ARRAY; + case Types.BIT: + case Types.BOOLEAN: + return RecordFieldType.BOOLEAN; + case Types.CHAR: + return RecordFieldType.CHAR; + case Types.DATE: + return RecordFieldType.DATE; + case Types.DECIMAL: + case Types.DOUBLE: + case Types.NUMERIC: + case Types.REAL: + return RecordFieldType.DOUBLE; + case Types.FLOAT: + return RecordFieldType.FLOAT; + case Types.INTEGER: + return RecordFieldType.INT; + case Types.SMALLINT: + return RecordFieldType.SHORT; + case Types.TINYINT: + return RecordFieldType.BYTE; + case Types.LONGNVARCHAR: + case Types.LONGVARCHAR: + case Types.NCHAR: + case Types.NULL: + case Types.NVARCHAR: + case Types.VARCHAR: + return RecordFieldType.STRING; + case Types.OTHER: + case Types.JAVA_OBJECT: + return RecordFieldType.RECORD; + case Types.TIME: + case Types.TIME_WITH_TIMEZONE: + return RecordFieldType.TIME; + case Types.TIMESTAMP: + case Types.TIMESTAMP_WITH_TIMEZONE: + return RecordFieldType.TIMESTAMP; + } + + return RecordFieldType.STRING; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/TypeMismatchException.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/TypeMismatchException.java b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/TypeMismatchException.java new file mode 100644 index 0000000..af5f909 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-service-api/src/main/java/org/apache/nifi/serialization/record/TypeMismatchException.java @@ -0,0 +1,28 @@ +/* + * 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. + */ + +package org.apache.nifi.serialization.record; + +public class TypeMismatchException extends RuntimeException { + public TypeMismatchException(String message) { + super(message); + } + + public TypeMismatchException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/pom.xml b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/pom.xml new file mode 100644 index 0000000..2a6f240 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/pom.xml @@ -0,0 +1,41 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <!-- + 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. + --> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-record-serialization-services-bundle</artifactId> + <version>1.2.0-SNAPSHOT</version> + </parent> + <artifactId>nifi-record-serialization-services-nar</artifactId> + <packaging>nar</packaging> + <properties> + <maven.javadoc.skip>true</maven.javadoc.skip> + <source.skip>true</source.skip> + </properties> + <dependencies> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-standard-services-api-nar</artifactId> + <type>nar</type> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-record-serialization-services</artifactId> + <version>1.2.0-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/nifi/blob/a88d3bfa/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/src/main/resources/META-INF/LICENSE ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/src/main/resources/META-INF/LICENSE b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/src/main/resources/META-INF/LICENSE new file mode 100644 index 0000000..581eac4 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-serialization-services-bundle/nifi-record-serialization-services-nar/src/main/resources/META-INF/LICENSE @@ -0,0 +1,269 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + +APACHE NIFI SUBCOMPONENTS: + +The Apache NiFi project contains subcomponents with separate copyright +notices and license terms. Your use of the source code for the these +subcomponents is subject to the terms and conditions of the following +licenses. + +The binary distribution of this product bundles 'Hamcrest' which is available +under a BSD license. More details found here: http://hamcrest.org. + + Copyright (c) 2000-2006, www.hamcrest.org + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. Redistributions in binary form must reproduce + the above copyright notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + Neither the name of Hamcrest nor the names of its contributors may be used to endorse + or promote products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +This product bundles 'asm' which is available under a 3-Clause BSD style license. +For details see http://asm.ow2.org/asmdex-license.html + + Copyright (c) 2012 France Télécom + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +
