<commit_before>/**
 * Copyright (C) 2013 <EMAIL> (<EMAIL>)
 *
 * 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 io.motown.ocpp.websocketjson;

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import io.motown.domain.api.chargingstation.*;
import io.motown.domain.api.security.AddOnIdentity;
import io.motown.domain.api.security.TypeBasedAddOnIdentity;
import io.motown.ocpp.viewmodel.domain.DomainService;
import io.motown.ocpp.websocketjson.request.handler.*;
import io.motown.ocpp.websocketjson.response.handler.*;
import io.motown.ocpp.websocketjson.schema.MessageProcUri;
import io.motown.ocpp.websocketjson.schema.SchemaValidator;
import io.motown.ocpp.websocketjson.schema.generated.v15.*;
import io.motown.ocpp.websocketjson.wamp.WampMessage;
import io.motown.ocpp.websocketjson.wamp.WampMessageParser;
import org.atmosphere.websocket.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

public class OcppJsonService {

    public static final String PROTOCOL_IDENTIFIER = OcppWebSocketRequestHandler.PROTOCOL_IDENTIFIER;
    private static final Logger LOG = LoggerFactory.getLogger(OcppJsonService.class);
    private static final String ADD_ON_TYPE = "OCPPJ15";
    private WampMessageParser wampMessageParser;
    private SchemaValidator schemaValidator;
    private DomainService domainService;
    private Gson gson;
    private AddOnIdentity addOnIdentity;
    /**
     * Map of requestHandlers, key is lowercase procUri.
     */
    private Map<MessageProcUri, RequestHandler> requestHandlers = new HashMap<>();

    /**
     * Map of sockets, key is charging station identifier.
     */
    private Map<String, WebSocket> sockets = new HashMap<>();

    /**
     * Map of response handlers, key is call id.
     */
    private Map<String, ResponseHandler> responseHandlers = new HashMap<>();

    public void handleMessage(ChargingStationId chargingStationId, Reader reader) {
        try {
            WampMessage wampMessage = wampMessageParser.parseMessage(reader);

            LOG.info("Received call from [{}]: {}", chargingStationId.getId(), wampMessage.getPayloadAsString());

            if (WampMessage.CALL == wampMessage.getMessageType()) {
                if (!schemaValidator.isValidRequest(wampMessage.getPayloadAsString(), wampMessage.getProcUri())) {
                    LOG.error("Cannot continue processing invalid request for [{}].", chargingStationId.getId());
                    WampMessage wampErrorMessage = new WampMessage(WampMessage.CALL_ERROR, wampMessage.getCallId(), null);
                    sendWampMessage(wampErrorMessage, chargingStationId);
                    return;
                }

                processWampMessage(chargingStationId, wampMessage);
            } else if (WampMessage.CALL_RESULT == wampMessage.getMessageType()) {
                ResponseHandler responseHandler = responseHandlers.get(wampMessage.getCallId());
                if (responseHandler != null) {
                    responseHandler.handle(chargingStationId, wampMessage, gson, domainService, addOnIdentity);

                    // handled so we remove the handler
                    responseHandlers.remove(wampMessage.getCallId());
                } else {
                    LOG.warn("No response handler found for callId [{}]", wampMessage.getCallId());
                }
            }
        } catch (IllegalArgumentException iae) {
            //Unable to send back a WAMP error at this level, as we are not able to access the callId
            LOG.error("Unable to handle message", iae);
        } catch (IOException ioe) {
            LOG.error("Unable to parse message", ioe);
        }

    }

    /**
     * Send a request to a charging station to change a configuration item.
     *
     * @param chargingStationId the charging station's id.
     * @param configurationItem the configuration item to change.
     * @param correlationToken  the token to correlate commands and events that belong together.
     */
    public void changeConfiguration(ChargingStationId chargingStationId, ConfigurationItem configurationItem, CorrelationToken correlationToken) {
        Changeconfiguration changeConfigurationRequest = new Changeconfiguration();
        changeConfigurationRequest.setKey(configurationItem.getKey());
        changeConfigurationRequest.setValue(configurationItem.getValue());

        responseHandlers.put(correlationToken.getToken(), new ChangeConfigurationResponseHandler(configurationItem, correlationToken));

        WampMessage wampMessage = new WampMessage(WampMessage.CALL, correlationToken.getToken(), MessageProcUri.CHANGE_CONFIGURATION, changeConfigurationRequest);
        sendWampMessage(wampMessage, chargingStationId);
    }

    public void getConfiguration(ChargingStationId chargingStationId) {

        CorrelationToken correlationToken = new CorrelationToken();
        Getconfiguration getConfigurationRequest = new Getconfiguration();

        responseHandlers.put(correlationToken.getToken(), new GetConfigurationResponseHandler(correlationToken));

        WampMessage wampMessage = new WampMessage(WampMessage.CALL, correlationToken.getToken(), MessageProcUri.GET_CONFIGURATION, getConfigurationRequest);
        sendWampMessage(wampMessage, chargingStationId);
    }

    public void getDiagnostics(ChargingStationId chargingStationId, int numRetries, int retryInterval, Date start, Date stop, String uploadLocation, CorrelationToken correlationToken) {
        Getdiagnostics getDiagnosticsRequest = new Getdiagnostics();
        try {
            getDiagnosticsRequest.setLocation(new URI(uploadLocation));
            getDiagnosticsRequest.setRetries(numRetries);
            getDiagnosticsRequest.setRetryInterval(retryInterval);
            getDiagnosticsRequest.setStartTime(start);
            getDiagnosticsRequest.setStopTime(stop);

            responseHandlers.put(correlationToken.getToken(), new GetDiagnosticsResponseHandler(correlationToken));

            WampMessage wampMessage = new WampMessage(WampMessage.CALL, correlationToken.getToken(), MessageProcUri.GET_DIAGNOSTICS, getDiagnosticsRequest);

            sendWampMessage(wampMessage, chargingStationId);
        } catch (URISyntaxException e) {
            LOG.error("Unable to perform get diagnostics request due to an invalid upload URI.", e);
        }
    }

    public void updateFirmware(ChargingStationId chargingStationId, Date retrieveDate, Map<String, String> attributes, String updateLocation) {<commit_msg>Fixed an issue with sending GetDiagnostics.req<commit_after>/**
 * Copyright (C) 2013 Motown.IO (<EMAIL>)
 *
 * 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 io.motown.ocpp.websocketjson;

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import io.motown.domain.api.chargingstation.*;
import io.motown.domain.api.security.AddOnIdentity;
import io.motown.domain.api.security.TypeBasedAddOnIdentity;
import io.motown.ocpp.viewmodel.domain.DomainService;
import io.motown.ocpp.websocketjson.request.handler.*;
import io.motown.ocpp.websocketjson.response.handler.*;
import io.motown.ocpp.websocketjson.schema.MessageProcUri;
import io.motown.ocpp.websocketjson.schema.SchemaValidator;
import io.motown.ocpp.websocketjson.schema.generated.v15.*;
import io.motown.ocpp.websocketjson.wamp.WampMessage;
import io.motown.ocpp.websocketjson.wamp.WampMessageParser;
import org.atmosphere.websocket.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

public class OcppJsonService {

    public static final String PROTOCOL_IDENTIFIER = OcppWebSocketRequestHandler.PROTOCOL_IDENTIFIER;
    private static final Logger LOG = LoggerFactory.getLogger(OcppJsonService.class);
    private static final String ADD_ON_TYPE = "OCPPJ15";
    private WampMessageParser wampMessageParser;
    private SchemaValidator schemaValidator;
    private DomainService domainService;
    private Gson gson;
    private AddOnIdentity addOnIdentity;
    /**
     * Map of requestHandlers, key is lowercase procUri.
     */
    private Map<MessageProcUri, RequestHandler> requestHandlers = new HashMap<>();

    /**
     * Map of sockets, key is charging station identifier.
     */
    private Map<String, WebSocket> sockets = new HashMap<>();

    /**
     * Map of response handlers, key is call id.
     */
    private Map<String, ResponseHandler> responseHandlers = new HashMap<>();

    public void handleMessage(ChargingStationId chargingStationId, Reader reader) {
        try {
            WampMessage wampMessage = wampMessageParser.parseMessage(reader);

            LOG.info("Received call from [{}]: {}", chargingStationId.getId(), wampMessage.getPayloadAsString());

            if (WampMessage.CALL == wampMessage.getMessageType()) {
                if (!schemaValidator.isValidRequest(wampMessage.getPayloadAsString(), wampMessage.getProcUri())) {
                    LOG.error("Cannot continue processing invalid request for [{}].", chargingStationId.getId());
                    WampMessage wampErrorMessage = new WampMessage(WampMessage.CALL_ERROR, wampMessage.getCallId(), null);
                    sendWampMessage(wampErrorMessage, chargingStationId);
                    return;
                }

                processWampMessage(chargingStationId, wampMessage);
            } else if (WampMessage.CALL_RESULT == wampMessage.getMessageType()) {
                ResponseHandler responseHandler = responseHandlers.get(wampMessage.getCallId());
                if (responseHandler != null) {
                    responseHandler.handle(chargingStationId, wampMessage, gson, domainService, addOnIdentity);

                    // handled so we remove the handler
                    responseHandlers.remove(wampMessage.getCallId());
                } else {
                    LOG.warn("No response handler found for callId [{}]", wampMessage.getCallId());
                }
            }
        } catch (IllegalArgumentException iae) {
            //Unable to send back a WAMP error at this level, as we are not able to access the callId
            LOG.error("Unable to handle message", iae);
        } catch (IOException ioe) {
            LOG.error("Unable to parse message", ioe);
        }

    }

    /**
     * Send a request to a charging station to change a configuration item.
     *
     * @param chargingStationId the charging station's id.
     * @param configurationItem the configuration item to change.
     * @param correlationToken  the token to correlate commands and events that belong together.
     */
    public void changeConfiguration(ChargingStationId chargingStationId, ConfigurationItem configurationItem, CorrelationToken correlationToken) {
        Changeconfiguration changeConfigurationRequest = new Changeconfiguration();
        changeConfigurationRequest.setKey(configurationItem.getKey());
        changeConfigurationRequest.setValue(configurationItem.getValue());

        responseHandlers.put(correlationToken.getToken(), new ChangeConfigurationResponseHandler(configurationItem, correlationToken));

        WampMessage wampMessage = new WampMessage(WampMessage.CALL, correlationToken.getToken(), MessageProcUri.CHANGE_CONFIGURATION, changeConfigurationRequest);
        sendWampMessage(wampMessage, chargingStationId);
    }

    public void getConfiguration(ChargingStationId chargingStationId) {

        CorrelationToken correlationToken = new CorrelationToken();
        Getconfiguration getConfigurationRequest = new Getconfiguration();

        responseHandlers.put(correlationToken.getToken(), new GetConfigurationResponseHandler(correlationToken));

        WampMessage wampMessage = new WampMessage(WampMessage.CALL, correlationToken.getToken(), MessageProcUri.GET_CONFIGURATION, getConfigurationRequest);
        sendWampMessage(wampMessage, chargingStationId);
    }

    public void getDiagnostics(ChargingStationId chargingStationId, Integer numRetries, Integer retryInterval, Date start, Date stop, String uploadLocation, CorrelationToken correlationToken) {
        Getdiagnostics getDiagnosticsRequest = new Getdiagnostics();
        try {
            getDiagnosticsRequest.setLocation(new URI(uploadLocation));
            getDiagnosticsRequest.setRetries(numRetries);
            getDiagnosticsRequest.setRetryInterval(retryInterval);
            getDiagnosticsRequest.setStartTime(start);
            getDiagnosticsRequest.setStopTime(stop);

            responseHandlers.put(correlationToken.getToken(), new GetDiagnosticsResponseHandler(correlationToken));

            WampMessage wampMessage = new WampMessage(WampMessage.CALL, correlationToken.getToken(), MessageProcUri.GET_DIAGNOSTICS, getDiagnosticsRequest);

            sendWampMessage(wampMessage, chargingStationId);
        } catch (URISyntaxException e) {
            LOG.error("Unable to perform get diagnostics request due to an invalid upload URI.", e);
        }
    }

    public void updateFirmware(ChargingStationId chargingStationId, Date retrieveDate, Map<String, String> attributes, String updateLocation) {
{'fraction_non_alphanumeric': 0.08365177516848468, 'fraction_numerical': 0.0019453901201973182, 'mean_word_length': 3.6312741312741315, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5531391', 'n_tokens_mistral': 3697, 'n_tokens_neox': 3593, 'n_words': 931}