/**
* Copyright 2016 Hortonworks.
*
* 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 com.hortonworks.registries.schemaregistry.serde;
import com.hortonworks.registries.common.Schema;
import com.hortonworks.registries.schemaregistry.serde.pull.FieldValueContext;
import com.hortonworks.registries.schemaregistry.serde.pull.PullDeserializer;
import com.hortonworks.registries.schemaregistry.serde.pull.PullEventContext;
import com.hortonworks.registries.schemaregistry.serde.pull.StartRecordContext;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
/**
* Sample {@link PullDeserializer} implementation
*/
public class SamplePullDeserializer implements PullDeserializer<SchemaDetails, Schema.Field> {
private final SchemaDetails schemaDetails;
private final BufferedReader payloadReader;
private State nextState = State.START_RECORD;
private String currentLine;
private String[] currentFields;
private int currentFieldIndex;
public SamplePullDeserializer(SchemaDetails schemaDetails, InputStream payloadInputStream) {
this.schemaDetails = schemaDetails;
this.payloadReader = new BufferedReader(new InputStreamReader(payloadInputStream));
}
@Override
public boolean hasNext() throws SerDesException {
return (nextState != State.END_DESERIALIZE);
}
@Override
public PullEventContext<Schema.Field> next() throws SerDesException {
PullEventContext<Schema.Field> context;
if (isStartEvent()) {
try {
currentLine = payloadReader.readLine();
} catch (IOException e) {
throw new SerDesException(e);
}
nextState = currentLine != null ? State.PROCESS_FIELDS : State.END_DESERIALIZE;
context = new StartRecordContext<>();
} else {
if (currentFields == null) {
currentFields = currentLine.split(",");
currentFieldIndex = 0;
}
// when there are no field/values in current event return null
final MyFieldValue fieldValue = currentFields.length > 0 ? new MyFieldValue(currentFields[currentFieldIndex++]) : null;
context = new FieldValueContext<>(fieldValue);
if (currentFieldIndex == currentFields.length) {
nextState = State.START_RECORD;
currentFields = null;
}
}
return context;
}
private boolean isStartEvent() {
return nextState == State.START_RECORD;
}
@Override
public SchemaDetails schema() {
return schemaDetails;
}
@Override
public void close() throws Exception {
payloadReader.close();
}
@Override
public void init(Map<String, ?> config) {
}
private class MyFieldValue implements PullEventContext.FieldValue<Schema.Field> {
private final String fieldPayload;
private final int separatorIndex;
public MyFieldValue(String fieldPayload) {
this.fieldPayload = fieldPayload;
separatorIndex = fieldPayload.indexOf(":");
if (separatorIndex == -1) {
throw new RuntimeException("Invalid field payload format");
}
}
@Override
public Schema.Field field() {
return Schema.Field.of(fieldPayload.substring(0, separatorIndex), Schema.Type.STRING);
}
@Override
public Object value() {
return fieldPayload.substring(separatorIndex + 1);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MyFieldValue)) return false;
MyFieldValue that = (MyFieldValue) o;
if (separatorIndex != that.separatorIndex) return false;
return fieldPayload.equals(that.fieldPayload);
}
@Override
public int hashCode() {
int result = fieldPayload.hashCode();
result = 31 * result + separatorIndex;
return result;
}
}
}