/* * 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; import org.apache.nifi.serialization.record.SchemaIdentifier; public class SimpleRecordSchema implements RecordSchema { private final List<RecordField> fields; private final Map<String, Integer> fieldIndices; private final boolean textAvailable; private final String text; private final String schemaFormat; private final SchemaIdentifier schemaIdentifier; public SimpleRecordSchema(final List<RecordField> fields) { this(fields, createText(fields), null, false, SchemaIdentifier.EMPTY); } public SimpleRecordSchema(final List<RecordField> fields, final SchemaIdentifier id) { this(fields, createText(fields), null, false, id); } public SimpleRecordSchema(final List<RecordField> fields, final String text, final String schemaFormat, final SchemaIdentifier id) { this(fields, text, schemaFormat, true, id); } private SimpleRecordSchema(final List<RecordField> fields, final String text, final String schemaFormat, final boolean textAvailable, final SchemaIdentifier id) { this.text = text; this.schemaFormat = schemaFormat; this.schemaIdentifier = id; this.textAvailable = textAvailable; this.fields = Collections.unmodifiableList(new ArrayList<>(fields)); this.fieldIndices = new HashMap<>(fields.size()); int index = 0; for (final RecordField field : fields) { Integer previousValue = fieldIndices.put(field.getFieldName(), index); if (previousValue != null) { throw new IllegalArgumentException("Two fields are given with the same name (or alias) of '" + field.getFieldName() + "'"); } for (final String alias : field.getAliases()) { previousValue = fieldIndices.put(alias, index); if (previousValue != null) { throw new IllegalArgumentException("Two fields are given with the same name (or alias) of '" + field.getFieldName() + "'"); } } index++; } } @Override public Optional<String> getSchemaText() { if (textAvailable) { return Optional.ofNullable(text); } else { return Optional.empty(); } } @Override public Optional<String> getSchemaFormat() { return Optional.ofNullable(schemaFormat); } @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(); } @Override public Optional<RecordField> getField(final String fieldName) { final OptionalInt indexOption = getFieldIndex(fieldName); if (indexOption.isPresent()) { return Optional.of(fields.get(indexOption.getAsInt())); } return 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(); } private static String createText(final List<RecordField> fields) { 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(); } @Override public String toString() { return text; } @Override public SchemaIdentifier getIdentifier() { return schemaIdentifier; } }