org.opendaylight.streamhandler.impl.StreamhandlerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.streamhandler.impl.StreamhandlerImpl.java

Source

/*
 * Copyright (c) 2015 Tata Consultancy services and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.streamhandler.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.PersistEventInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QueryEventsInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QueryEventsOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QueryLuceneApiInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QueryLuceneApiOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QueryLuceneRelativeApiInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QueryLuceneRelativeApiOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QuerySqlApiInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QuerySqlApiOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QuerySqlApiOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QuerySqlRelativeApiInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QuerySqlRelativeApiOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.QuerySqlRelativeApiOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.StreamhandlerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.query.sql.relative.api.output.Records;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.query.sql.relative.api.output.RecordsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.record.Fields;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.record.FieldsBuilder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.SettableFuture;
import com.sun.jersey.api.client.ClientResponse;

public class StreamhandlerImpl implements StreamhandlerService, AutoCloseable {

    private static final String ORDER_BY = " ORDER BY ";
    private static final String WHERE = " WHERE ";
    private static final String AND = " AND ";
    private static final String CONVERT_QUERY_STREAM_TO_JSON = "convert_from(centinel.stream.stringdata, 'json')";
    private static final String CONVERT_QUERY_ALERT_TO_JSON = "convert_from(centinel.alert.stringdata, 'json')";
    private static final String CONVERT_QUERY_DASHBOARD_TO_JSON = "convert_from(centinel.dashboard.stringdata, 'json')";

    private static final Logger LOG = LoggerFactory.getLogger(StreamhandlerImpl.class);

    private final ExecutorService executor;
    PersistEvent client = null;
    CommonServices commonServices = null;

    Calendar now = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat(StreamConstants.SDF_DATE_FORMAT);

    public StreamhandlerImpl() {
        commonServices = CommonServices.getInstance();
        executor = Executors.newFixedThreadPool(1);
    }

    @Override
    public void close() throws Exception {

        executor.shutdown();
    }

    @Override
    public Future<RpcResult<Void>> persistEvent(PersistEventInput input) {
        final SettableFuture<RpcResult<Void>> futureResult = SettableFuture.create();
        boolean result = true;
        try {
            // Initialize client with the remote Flume agent's host and port
            if (client == null) {
                client = new PersistEvent(commonServices.flumeHostname, commonServices.flumePort);
            }
            result = client.sendDataToFlume(input);
        } catch (Exception e) {
            futureResult.set(RpcResultBuilder.<Void>failed().build());
            LOG.error("Unable to save data " + e.getMessage(), e);
        }
        if (!result) {
            futureResult.set(RpcResultBuilder.<Void>failed().build());
        } else {
            futureResult.set(RpcResultBuilder.<Void>success().build());
        }
        return futureResult;
    }

    @Override
    public Future<RpcResult<QuerySqlRelativeApiOutput>> querySqlRelativeApi(QuerySqlRelativeApiInput input) {

        final SettableFuture<RpcResult<QuerySqlRelativeApiOutput>> futureResult = SettableFuture.create();
        String query = input.getQueryString();
        Short timeRange = input.getTimeRange();
        Short limit = input.getLimit();
        List<String> eventFields = input.getEventFields();
        List<Map<String, Object>> output = null;

        if (query == null) {
            return Futures.immediateFailedCheckedFuture(
                    new TransactionCommitFailedException("invalid-input", RpcResultBuilder
                            .newError(ErrorType.APPLICATION, "Field missing", "Mandatory field Query missing")));
        }
        if (limit == null) {
            limit = Short.parseShort(commonServices.defaultLimit);
        }
        if (timeRange == null && limit != null) {
            if (commonServices.dbType.equalsIgnoreCase(StreamConstants.HBASE)) {
                if (checkIfQueryContainsStreamWithSpaces(query)) {
                    query = updateWhenQueryContainsStream(query);
                    query = amendLimitToQuery(query, limit);
                } else if (checkIfQueryContainsAlertWithSpaces(query)) {
                    query = updateWhenQueryContainsAlert(query);
                    query = amendLimitToQuery(query, limit);
                } else if (checkIfQueryContainsDashboardWithSpaces(query)) {
                    query = updateWhenQueryContainsDashboard(query);
                    query = amendLimitToQuery(query, limit);
                } else if (checkIfQueryContainsData(query)) {
                    query = updateWhenQueryContainsData(query);
                    query = amendLimitToQuery(query, limit);
                } else {

                    return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException(
                            "invalid-input", RpcResultBuilder.newError(ErrorType.APPLICATION, "invalid query",
                                    "supported columns are stream, alert, dashboard and data ")));
                }

            } else {
                return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("invalid-input",
                        RpcResultBuilder.newError(ErrorType.APPLICATION, "DB type not supported",
                                "DB type " + commonServices.dbType + "not supported")));

            }

        } else if (timeRange != null && limit != null) {
            now.add(Calendar.MINUTE, -timeRange);
            String formattedTimestamp = sdf.format(now.getTime());

            if (commonServices.dbType.equalsIgnoreCase(StreamConstants.HBASE)) {
                if (checkIfQueryContainsStreamWithSpaces(query)) {
                    query = replaceFirstCentinelForDBType(query);
                    if (checkIfQueryContainsStreamDot(query)) {
                        query = query.replace(StreamConstants.STREAM_DOT,
                                StreamConstants.CENTINEL_DOT + StreamConstants.STREAM_DOT);
                        query = query + " AND centinel.stream.event_timestamp>="
                                + getSingleQuotedValue(formattedTimestamp);
                    } else if (!checkIfQueryContainsStreamDot(query)) {
                        query = query + " where centinel.stream.event_timestamp>="
                                + getSingleQuotedValue(formattedTimestamp);
                    }
                    query = replaceFirstStream(query);
                    query = amendLimitToQuery(query, limit);
                } else if (checkIfQueryContainsAlertWithSpaces(query)) {
                    query = replaceFirstCentinelForDBType(query);
                    if (checkIfQueryContainsAlertDot(query)) {
                        query = query.replace(StreamConstants.ALERT_DOT,
                                StreamConstants.CENTINEL_DOT + StreamConstants.ALERT_DOT);
                        query = query + " AND centinel.alert.check_result:triggeredAt>="
                                + getSingleQuotedValue(formattedTimestamp);
                    } else if (!checkIfQueryContainsAlertDot(query)) {
                        query = query + " where centinel.alert.check_result:triggeredAt>="
                                + getSingleQuotedValue(formattedTimestamp);
                    }
                    query = replaceFirstAlert(query);
                    query = amendLimitToQuery(query, limit);
                } else if (checkIfQueryContainsDashboardWithSpaces(query)) {
                    query = replaceFirstCentinelForDBType(query);

                    if (checkIfQueryContainsDashboardDot(query)) {
                        query = query.replace(StreamConstants.DASHBOARD_DOT,
                                StreamConstants.CENTINEL_DOT + StreamConstants.DASHBOARD_DOT);
                        query = query + AND + "centinel.dashboard.resetTime>="
                                + getSingleQuotedValue(formattedTimestamp);

                    } else if (!checkIfQueryContainsDashboardDot(query)) {
                        query = query + WHERE + "centinel.dashboard.resetTime>="
                                + getSingleQuotedValue(formattedTimestamp);
                    }
                    query = replaceFirstDashboard(query);
                    query = amendLimitToQuery(query, limit);

                } else if (checkIfQueryContainsData(query)) {
                    query = updateWhenQueryContainsData(query);
                    query = amendLimitToQuery(query, limit);
                } else {
                    return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException(
                            "invalid-input", RpcResultBuilder.newError(ErrorType.APPLICATION, "invalid query",
                                    "supported columns are stream, alert, dashboard and data ")));
                }
            } else {
                return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("invalid-input",
                        RpcResultBuilder.newError(ErrorType.APPLICATION, "DB type not supported",
                                "DB type " + commonServices.dbType + "not supported")));
            }
        }

        query = query.replace(StreamConstants.COLON, StreamConstants.UNDERSCORE);
        query = commonServices.matchRegEx(query);

        Map<String, String> drillQuery = new HashMap<String, String>();
        drillQuery.put(StreamConstants.QUERY_TYPE, StreamConstants.SQL);
        drillQuery.put(StreamConstants.QUERY, query);

        LOG.info("Drill Query: " + query);

        ClientResponse response = commonServices.drillRESTPost(drillQuery, commonServices.drillHostname,
                commonServices.drillPort);

        if (response != null && response.getStatus() != 200) {
            LOG.info("Error in Drill: " + response.getStatus());
            return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("invalid-input",
                    RpcResultBuilder.newError(ErrorType.APPLICATION, "Error connecting drill",
                            response.getClientResponseStatus().toString())));

        } else {

            output = commonServices.parseResponse(response.getEntity(String.class), eventFields);

        }

        List<Records> recordList = new ArrayList<Records>();

        for (Map<String, Object> out : output) {

            Iterator<Entry<String, Object>> itr = out.entrySet().iterator();
            List<Fields> fieldsList = new ArrayList<Fields>();
            while (itr.hasNext()) {
                Entry<String, Object> obj = itr.next();
                fieldsList.add(new FieldsBuilder().setFieldValue(obj.getValue().toString())
                        .setFieldName(obj.getKey()).build());
            }

            Records recordObj = new RecordsBuilder().setFields(fieldsList).build();
            recordList.add(recordObj);
        }

        QuerySqlRelativeApiOutput queryOutput = new QuerySqlRelativeApiOutputBuilder().setRecords(recordList)
                .build();
        futureResult.set(RpcResultBuilder.<QuerySqlRelativeApiOutput>success(queryOutput).build());
        return futureResult;
    }

    @Override
    public Future<RpcResult<QuerySqlApiOutput>> querySqlApi(QuerySqlApiInput input) {

        final SettableFuture<RpcResult<QuerySqlApiOutput>> futureResult = SettableFuture.create();
        String query = input.getQueryString();
        String fromTime = input.getFromTime();
        String toTime = input.getToTime();
        Short limit = input.getLimit();
        List<String> eventFields = input.getEventFields();
        List<Map<String, Object>> output = null;

        if (query == null) {
            return Futures.immediateFailedCheckedFuture(
                    new TransactionCommitFailedException("invalid-input", RpcResultBuilder
                            .newError(ErrorType.APPLICATION, "Field missing", "Mandatory field Query missing")));

        }
        if (limit == null) {
            limit = Short.parseShort(commonServices.defaultLimit);
        }
        if (fromTime == null && toTime == null && limit != null) {
            if (commonServices.dbType.equalsIgnoreCase(StreamConstants.HBASE)) {
                if (checkIfQueryContainsStreamWithSpaces(query)) {
                    query = updateWhenQueryContainsStream(query);
                    query = query + ORDER_BY + "centinel.stream.event_timestamp DESC limit " + limit;
                } else if (checkIfQueryContainsAlertWithSpaces(query)) {
                    query = updateWhenQueryContainsAlert(query);
                    query = query + ORDER_BY + "centinel.alert.check_result:triggeredAt DESC limit " + limit;
                } else if (checkIfQueryContainsDashboardWithSpaces(query)) {
                    query = updateWhenQueryContainsDashboard(query);
                    query = query + ORDER_BY + "centinel.dashboard.resetTime DESC limit " + limit;
                } else if (checkIfQueryContainsData(query)) {
                    query = updateWhenQueryContainsData(query);
                    query = amendLimitToQuery(query, limit);
                } else {

                    return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException(
                            "invalid-input", RpcResultBuilder.newError(ErrorType.APPLICATION, "invalid query",
                                    "supported columns are stream, alert, dashboard and data ")));
                }

            } else {
                return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("invalid-input",
                        RpcResultBuilder.newError(ErrorType.APPLICATION, "DB type not supported",
                                "DB type " + commonServices.dbType + "not supported")));

            }
        } else if (fromTime != null && toTime != null && limit != null) {
            if (commonServices.dbType.equalsIgnoreCase(StreamConstants.HBASE)) {
                if (query.contains(StreamConstants.STREAM)) {
                    query = replaceFirstCentinelForDBType(query);
                    if (checkIfQueryContainsStreamDot(query)) {
                        query = query.replace(StreamConstants.STREAM_DOT,
                                StreamConstants.CENTINEL_DOT + StreamConstants.STREAM_DOT);
                        query = query + AND + "centinel.stream.event_timestamp>=" + getSingleQuotedValue(fromTime)
                                + AND + "centinel.stream.event_timestamp<=" + getSingleQuotedValue(toTime);
                    } else if (!checkIfQueryContainsStreamDot(query)) {
                        query = query + WHERE + "centinel.stream.event_timestamp>=" + getSingleQuotedValue(fromTime)
                                + AND + "centinel.stream.event_timestamp<=" + getSingleQuotedValue(toTime);
                    }
                    query = replaceFirstStream(query);
                    query = amendLimitToQuery(query, limit);
                } else if (checkIfQueryContainsAlertWithSpaces(query)) {
                    query = replaceFirstCentinelForDBType(query);
                    if (checkIfQueryContainsAlertDot(query)) {
                        query = query.replace(StreamConstants.ALERT_DOT,
                                StreamConstants.CENTINEL_DOT + StreamConstants.ALERT_DOT);
                        query = query + AND + "centinel.alert.check_result:triggeredAt>="
                                + getSingleQuotedValue(fromTime) + AND + "centinel.alert.check_result:triggeredAt<="
                                + getSingleQuotedValue(toTime);

                    } else if (!checkIfQueryContainsAlertDot(query)) {
                        query = query + WHERE + "centinel.alert.check_result:triggeredAt>="
                                + getSingleQuotedValue(fromTime) + AND + "centinel.alert.check_result:triggeredAt<="
                                + getSingleQuotedValue(toTime);
                    }
                    query = replaceFirstAlert(query);
                    query = amendLimitToQuery(query, limit);
                } else if (checkIfQueryContainsDashboardWithSpaces(query)) {
                    query = replaceFirstCentinelForDBType(query);
                    if (checkIfQueryContainsDashboardDot(query)) {
                        query = query.replace(StreamConstants.DASHBOARD_DOT,
                                StreamConstants.CENTINEL_DOT + StreamConstants.DASHBOARD_DOT);
                        query = query + AND + "centinel.dashboard.resetTime>=" + getSingleQuotedValue(fromTime)
                                + AND + "centinel.dashboard.resetTime<=" + getSingleQuotedValue(toTime);

                    } else if (!checkIfQueryContainsDashboardDot(query)) {
                        query = query + WHERE + "centinel.dashboard.resetTime>=" + getSingleQuotedValue(fromTime)
                                + AND + "centinel.dashboard.resetTime<=" + getSingleQuotedValue(toTime);
                    }
                    query = replaceFirstDashboard(query);
                    query = amendLimitToQuery(query, limit);
                } else if (checkIfQueryContainsData(query)) {
                    query = updateWhenQueryContainsData(query);
                    query = amendLimitToQuery(query, limit);
                } else {

                    return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException(
                            "invalid-input", RpcResultBuilder.newError(ErrorType.APPLICATION, "invalid query",
                                    "supported columns are stream, alert, dashboard and data ")));
                }

            } else {
                return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("invalid-input",
                        RpcResultBuilder.newError(ErrorType.APPLICATION, "DB type not supported",
                                "DB type " + commonServices.dbType + "not supported")));
            }
        }

        query = query.replace(StreamConstants.COLON, StreamConstants.UNDERSCORE);
        query = commonServices.matchRegEx(query);

        Map<String, String> drillQuery = new HashMap<String, String>();
        drillQuery.put(StreamConstants.QUERY_TYPE, StreamConstants.SQL);
        drillQuery.put(StreamConstants.QUERY, query);
        LOG.info("Drill Query: " + query);

        ClientResponse response = commonServices.drillRESTPost(drillQuery, commonServices.drillHostname,
                commonServices.drillPort);

        if (response != null && response.getStatus() != 200) {
            LOG.info("Error in Drill: " + response.getStatus());
            return Futures.immediateFailedCheckedFuture(new TransactionCommitFailedException("invalid-input",
                    RpcResultBuilder.newError(ErrorType.APPLICATION, "Error connecting drill",
                            response.getClientResponseStatus().toString())));
        } else {

            output = commonServices.parseResponse(response.getEntity(String.class), eventFields);

        }

        List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.query.sql.api.output.Records> recordList = new ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.query.sql.api.output.Records>();

        for (Map<String, Object> out : output) {

            Iterator<Entry<String, Object>> itr = out.entrySet().iterator();
            List<Fields> fieldsList = new ArrayList<Fields>();
            while (itr.hasNext()) {
                Entry<String, Object> obj = itr.next();
                fieldsList.add(new FieldsBuilder().setFieldValue(obj.getValue().toString())
                        .setFieldName(obj.getKey()).build());
            }

            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.query.sql.api.output.Records recordObj = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.streamhandler.rev150105.query.sql.api.output.RecordsBuilder()
                    .setFields(fieldsList).build();
            recordList.add(recordObj);
        }

        QuerySqlApiOutput queryOutput = new QuerySqlApiOutputBuilder().setRecords(recordList).build();
        futureResult.set(RpcResultBuilder.<QuerySqlApiOutput>success(queryOutput).build());
        return futureResult;

    }

    @Override
    public Future<RpcResult<QueryEventsOutput>> queryEvents(QueryEventsInput input) {
        return null;
    }

    @Override
    public Future<RpcResult<QueryLuceneRelativeApiOutput>> queryLuceneRelativeApi(
            QueryLuceneRelativeApiInput input) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Future<RpcResult<QueryLuceneApiOutput>> queryLuceneApi(QueryLuceneApiInput input) {
        // TODO Auto-generated method stub
        return null;
    }

    private boolean checkIfQueryContainsDashboardDot(String query) {
        return query.contains(StreamConstants.SPACE + StreamConstants.DASHBOARD_DOT);
    }

    private boolean checkIfQueryContainsAlertDot(String query) {
        return query.contains(StreamConstants.SPACE + StreamConstants.ALERT_DOT);
    }

    private boolean checkIfQueryContainsStreamDot(String query) {
        return query.contains(StreamConstants.SPACE + StreamConstants.STREAM_DOT);
    }

    private boolean checkIfQueryContainsData(String query) {
        return query.contains(StreamConstants.DATA);
    }

    private boolean checkIfQueryContainsDashboardWithSpaces(String query) {
        return query.contains(StreamConstants.SPACE + StreamConstants.DASHBOARD + StreamConstants.SPACE);
    }

    private boolean checkIfQueryContainsAlertWithSpaces(String query) {
        return query.contains(StreamConstants.SPACE + StreamConstants.ALERT + StreamConstants.SPACE);
    }

    private boolean checkIfQueryContainsStreamWithSpaces(String query) {
        return query.contains(StreamConstants.SPACE + StreamConstants.STREAM + StreamConstants.SPACE);
    }

    private String replaceFirstDashboard(String query) {
        return query.replaceFirst(StreamConstants.DASHBOARD, CONVERT_QUERY_DASHBOARD_TO_JSON);
    }

    private String amendLimitToQuery(String query, Short limit) {
        return query + StreamConstants.SPACE + StreamConstants.LIMIT + StreamConstants.SPACE + limit;
    }

    private String replaceFirstAlert(String query) {
        return query.replaceFirst(StreamConstants.ALERT, CONVERT_QUERY_ALERT_TO_JSON);
    }

    private String replaceFirstStream(String query) {
        return query.replaceFirst(StreamConstants.STREAM, CONVERT_QUERY_STREAM_TO_JSON);
    }

    private String replaceFirstCentinelForDBType(String query) {
        return query.replaceFirst(StreamConstants.CENTINEL, commonServices.dbType + StreamConstants.DOT_CENTINEL);
    }

    private String updateWhenQueryContainsData(String query) {
        query = replaceFirstCentinelForDBType(query);
        query = query.replace(StreamConstants.DATA_DOT, StreamConstants.CENTINEL_DOT + StreamConstants.DATA_DOT);
        query = query.replaceFirst(StreamConstants.DATA, "convert_from(centinel.stringdata.stringdata, 'json')");
        return query;
    }

    private String updateWhenQueryContainsDashboard(String query) {
        query = replaceFirstCentinelForDBType(query);
        query = query.replace(StreamConstants.DASHBOARD_DOT,
                StreamConstants.CENTINEL_DOT + StreamConstants.DASHBOARD_DOT);
        query = replaceFirstDashboard(query);
        return query;
    }

    private String updateWhenQueryContainsAlert(String query) {
        query = replaceFirstCentinelForDBType(query);
        query = query.replace(StreamConstants.ALERT_DOT, StreamConstants.CENTINEL_DOT + StreamConstants.ALERT_DOT);
        query = replaceFirstAlert(query);
        return query;
    }

    private String updateWhenQueryContainsStream(String query) {
        query = replaceFirstCentinelForDBType(query);
        query = query.replace(StreamConstants.STREAM_DOT,
                StreamConstants.CENTINEL_DOT + StreamConstants.STREAM_DOT);
        query = replaceFirstStream(query);
        return query;
    }

    // TODO : This can be moved to some Stream Utility class in future
    public String getSingleQuotedValue(String value) {
        return StreamConstants.SINGLE_QUOTE + value + StreamConstants.SINGLE_QUOTE;
    }
}