/* * Copyright 2013 NGDATA nv * * 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. */ package org.lilyproject.tools.import_.json; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.lilyproject.repository.api.Link; import org.lilyproject.repository.api.Record; import org.lilyproject.repository.api.RepositoryException; import java.math.BigDecimal; import java.net.URI; import java.util.List; /** * A specialized RecordReader which will drop fields containing empty strings, drop lists * containing zero entries, and drop nested records containing zero fields. * For fields in the root record, the fields are not just skipped, they are actively deleted * by adding them to the deleted fields (this last part is actually a feature of the * superclass, see {@link RecordReader#deleteNullFields()}). * * <p>This makes a lot of sense when the input jsons are generated by ETL jobs that don't * want to bother with having to change the structure of the JSON according to whether * a field has a value or not. Instead, they can use a fixed json structure into which * they just need to fill in the blanks.</p> */ public class IgnoreEmptyFieldsRecordReader extends RecordReader { public static final IgnoreEmptyFieldsRecordReader INSTANCE = new IgnoreEmptyFieldsRecordReader(); @Override protected Record readNestedRecord(ValueHandle handle, ReadContext context) throws InterruptedException, RepositoryException, JsonFormatException { Record record = super.readNestedRecord(handle, context); return record.getFields().isEmpty() ? null : record; } @Override protected String readString(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readString(handle, context); } @Override protected List<Object> readList(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { List<Object> result = super.readList(handle, context); return result != null && result.isEmpty() ? null : result; } @Override protected List<Object> readPath(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { List<Object> result = super.readPath(handle, context); return result != null && result.isEmpty() ? null : result; } @Override protected LocalDate readDate(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readDate(handle, context); } @Override protected DateTime readDateTime(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readDateTime(handle, context); } @Override protected Link readLink(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readLink(handle, context); } @Override protected Integer readInteger(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readInteger(handle, context); } @Override protected Long readLong(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readLong(handle, context); } @Override protected Double readDouble(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readDouble(handle, context); } @Override protected BigDecimal readDecimal(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readDecimal(handle, context); } @Override protected Boolean readBoolean(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readBoolean(handle, context); } @Override protected URI readUri(ValueHandle handle, ReadContext context) throws JsonFormatException, RepositoryException, InterruptedException { return isBlank(handle) ? null : super.readUri(handle, context); } protected boolean isBlank(ValueHandle handle) { return handle.node.isTextual() && handle.node.getTextValue().isEmpty(); } }