/*
* 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.processors.standard.relp.response;
import org.apache.nifi.processors.standard.relp.frame.RELPFrame;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
/**
* The data portion of a RELPFrame for a response:
*
* RSP-CODE [SP HUMANMSG] LF [CMDDATA]
*
*/
public class RELPResponse {
public static final int OK = 200;
public static final int ERROR = 500;
public static final String RSP_CMD = "rsp";
private final long txnr;
private final int code;
private final String message;
private final String data;
public RELPResponse(final long txnr, final int code) {
this(txnr, code, null, null);
}
public RELPResponse(final long txnr, final int code, final String message, final String data) {
this.txnr = txnr;
this.code = code;
this.message = message;
this.data = data;
}
/**
* Creates a RELPFrame where the data portion will contain this response.
*
* @param charset the character set to encode the response
*
* @return a RELPFrame for for this response
*/
public RELPFrame toFrame(final Charset charset) {
final StringBuilder builder = new StringBuilder();
builder.append(code);
if (message != null && !message.isEmpty()) {
builder.append((char)RELPFrame.SEPARATOR);
builder.append(message);
}
if (data != null) {
builder.append((char)RELPFrame.DELIMITER);
builder.append(data);
}
final byte[] data = builder.toString().getBytes(charset);
return new RELPFrame.Builder()
.txnr(txnr).command(RSP_CMD)
.dataLength(data.length).data(data)
.build();
}
/**
* Utility method to create a response to an open request.
*
* @param txnr the transaction number of the open request
* @param offers the accepted offers
*
* @return the RELPResponse for the given open request
*/
public static RELPResponse open(final long txnr, final Map<String,String> offers) {
int i = 0;
final StringBuilder sb = new StringBuilder();
for (final Map.Entry<String, String> entry : offers.entrySet()) {
if (i > 0) {
sb.append((char)RELPFrame.DELIMITER);
}
sb.append(entry.getKey());
if (entry.getValue() != null) {
sb.append('=');
sb.append(entry.getValue());
}
i++;
}
return new RELPResponse(txnr, OK, "OK", sb.toString());
}
/**
* Utility method to create a default "OK" response.
*
* @param txnr the transaction number being responded to
*
* @return a RELPResponse with a 200 code and a message of "OK"
*/
public static RELPResponse ok(final long txnr) {
return new RELPResponse(txnr, OK, "OK", null);
}
/**
* Utility method to create a default "ERROR" response.
*
* @param txnr the transaction number being responded to
*
* @return a RELPResponse with a 500 code and a message of "ERROR"
*/
public static RELPResponse error(final long txnr) {
return new RELPResponse(txnr, ERROR, "ERROR", null);
}
/**
* Parses the provided data into a Map of offers.
*
* @param data the data portion of a RELPFrame for an "open" command
* @param charset the charset to decode the data
*
* @return a Map of offers, or an empty Map if no data is provided
*/
public static Map<String,String> parseOffers(final byte[] data, final Charset charset) {
final Map<String, String> offers = new HashMap<>();
if (data == null || data.length == 0) {
return offers;
}
final String dataStr = new String(data, charset);
final String[] splits = dataStr.split("[" + (char)RELPFrame.DELIMITER + "]");
for (final String split : splits) {
final String[] fields = split.split( "=", 2);
if (fields.length > 1 ) {
offers.put(fields[0], fields[1]);
} else {
offers.put(fields[0], fields[0]);
}
}
return offers;
}
}