<commit_before>/* 
 * Copyright 2014 MICRORISC s.r.o.
 *
 * 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.microrisc.simply.iqrf.dpa.v22x.protocol;

import com.microrisc.simply.AbstractMessage;
import com.microrisc.simply.BaseCallResponse;
import com.microrisc.simply.CallRequest;
import com.microrisc.simply.NetworkData;
import com.microrisc.simply.NetworkLayerService;
import com.microrisc.simply.SimpleMessageSource;
import com.microrisc.simply.SimpleMethodMessageSource;
import com.microrisc.simply.SimplyException;
import com.microrisc.simply.asynchrony.BaseAsynchronousMessage;
import com.microrisc.simply.errors.NetworkInternalError;
import com.microrisc.simply.iqrf.dpa.DPA_ResponseCode;
import com.microrisc.simply.iqrf.dpa.asynchrony.DPA_AsynchronousMessage;
import com.microrisc.simply.iqrf.dpa.asynchrony.SimpleDPA_AsynchronousMessageSource;
import com.microrisc.simply.iqrf.dpa.broadcasting.BroadcastRequest;
import com.microrisc.simply.iqrf.dpa.broadcasting.BroadcastResult;
import com.microrisc.simply.iqrf.dpa.protocol.DPA_ProtocolProperties;
import com.microrisc.simply.iqrf.dpa.v22x.devices.Coordinator;
import com.microrisc.simply.iqrf.dpa.v22x.devices.FRC;
import com.microrisc.simply.iqrf.dpa.v22x.di_services.method_id_transformers.CoordinatorStandardTransformer;
import com.microrisc.simply.iqrf.dpa.v22x.di_services.method_id_transformers.FRCStandardTransformer;
import com.microrisc.simply.iqrf.dpa.v22x.typeconvertors.DPA_ConfirmationConvertor;
import com.microrisc.simply.iqrf.dpa.v22x.types.DPA_Confirmation;
import com.microrisc.simply.iqrf.dpa.v22x.protocol.timing.TimingParamsStorage;
import com.microrisc.simply.network.BaseNetworkData;
import com.microrisc.simply.protocol.AbstractProtocolLayer;
import com.microrisc.simply.protocol.CallRequestComparator;
import com.microrisc.simply.protocol.MessageConvertor;
import com.microrisc.simply.protocol.SimpleRequestToResponseMatcher;
import com.microrisc.simply.typeconvertors.ValueConversionException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.microrisc.simply.iqrf.dpa.v22x.init.NetworkInfo;

/**
 * Protocol layer based on DPA_ProtocolProperties of IQRF.
 * 
 * @author <NAME>
 * @author <NAME>
 */
//JUNE-2015 - improved determing and using RF mode
public final class DPA_ProtocolLayer 
extends AbstractProtocolLayer
implements ProtocolStateMachineListener
{
    /** Logger. */
    private static final Logger logger = LoggerFactory.getLogger(DPA_ProtocolLayer.class);
    
    
    
    
    /**
     * Binds sent requests with theirs time of sending.
     */
    private static class TimeRequest {
        // sent request
        CallRequest request;
        
        // time, at which the request was sent
        long sentTime;
        
        TimeRequest(CallRequest request, long sentTime) {
            this.request = request;
            this.sentTime = sentTime;
        }
        
        public String toString() {
            StringBuilder strBuilder = new StringBuilder();
            String NEW_LINE = System.getProperty("line.separator");

            strBuilder.append(this.getClass().getSimpleName() + " { " + NEW_LINE);
            strBuilder.append(" Request: " + request + NEW_LINE);
            strBuilder.append(" Sent: " + sentTime + NEW_LINE);
            strBuilder.append("}");

            return strBuilder.toString();
        }
    }
    
    // information about potentionally time unlimited request - i.e. request,
    // whose response time is not inherently bounded, i.e. discovery
    private static class TimeUnlimitedRequestInfo {
        Class devIface;
        Set<String> methodIds;
        
        public TimeUnlimitedRequestInfo(Class devIface, Set<String> methodIds) {
            this.devIface = devIface;
            this.methodIds = methodIds;
        }
    }
    
    // map of time unlimited requests
    private static Map<Class, TimeUnlimitedRequestInfo> timeUnlimitedRequestsMap = new HashMap<>();
    
    // initialize set of time unlimited requests
    private static void initTimeUnlimitedRequests() {
        Set<String> coordUnlimitedOperations = new HashSet<>();
        coordUnlimitedOperations.add(
                CoordinatorStandardTransformer
                .getInstance()
                .transform(Coordinator.MethodID.RUN_DISCOVERY)
        );
        
        coordUnlimitedOperations.add(
                CoordinatorStandardTransformer
                .getInstance()
                .transform(Coordinator.MethodID.BOND_NODE)
        );
        
        timeUnlimitedRequestsMap.put(
                Coordinator.class,
                new TimeUnlimitedRequestInfo(
                        Coordinator.class,
                        coordUnlimitedOperations
                )
        );
        
        Set<String> frcUnlimitedOperations = new HashSet<>();
        frcUnlimitedOperations.add(
                FRCStandardTransformer
                .getInstance()
                .transform(FRC.MethodID.SEND)
        );

/*        
        frcUnlimitedOperations.add(
                FRCStandardTransformer
                .getInstance()
                .transform(FRC.MethodID.EXTRA_RESULT)
        );
*/
        
        timeUnlimitedRequestsMap.put(
                FRC.class,
                new TimeUnlimitedRequestInfo(
                        FRC.class,
                        frcUnlimitedOperations
                )
        );
    }
    
    // static initializer
    static {
        initTimeUnlimitedRequests();
    }   
    
    // indicates, wheather the specified request is time unlimited
    private static boolean isTimeUnlimitedRequest(CallRequest request) {
        TimeUnlimitedRequestInfo unlimRequestInfo 
                = timeUnlimitedRequestsMap.get(request.getDeviceInterface());
        
        if ( unlimRequestInfo == null ) {
            return false;
        }
        
        return unlimRequestInfo.methodIds.contains(request.getMethodId());        
    }

    // indicates, wheather a timeout is defined by user
    private static boolean isTimeoutDefinedByUserRequest(long procTime) {
        
        if (procTime == -1)
            return false;
        
        return true;
    }
    
    // indicates, wheather a time unlimited request is in process
    private volatile boolean isTimeUnlimitedRequestInProcess = false;
    
    // indicates, wheather a timeout is defined by user
    private volatile boolean isTimeoutDefinedByUserRequestInProcess = false;
    
    /** Last sent request. */
    private TimeRequest lastRequest = null;
    
    /** List of all requests, which was sent to network layer. */
    private List<TimeRequest> sentRequests = new LinkedList<>();
    
    /** Synchronization object for {@code sentRequest} data structure. */
    private final Object synchroSentRequest = new Object();
   
    // timing parameters manager<commit_msg>Removed FRC SET command from set of potentionally unlimited operations in Protocol Layer.<commit_after>/* 
 * Copyright 2014 MICRORISC s.r.o.
 *
 * 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.microrisc.simply.iqrf.dpa.v22x.protocol;

import com.microrisc.simply.AbstractMessage;
import com.microrisc.simply.BaseCallResponse;
import com.microrisc.simply.CallRequest;
import com.microrisc.simply.NetworkData;
import com.microrisc.simply.NetworkLayerService;
import com.microrisc.simply.SimpleMessageSource;
import com.microrisc.simply.SimpleMethodMessageSource;
import com.microrisc.simply.SimplyException;
import com.microrisc.simply.asynchrony.BaseAsynchronousMessage;
import com.microrisc.simply.di_services.WaitingTimeoutService;
import com.microrisc.simply.errors.NetworkInternalError;
import com.microrisc.simply.iqrf.dpa.DPA_ResponseCode;
import com.microrisc.simply.iqrf.dpa.asynchrony.DPA_AsynchronousMessage;
import com.microrisc.simply.iqrf.dpa.asynchrony.SimpleDPA_AsynchronousMessageSource;
import com.microrisc.simply.iqrf.dpa.broadcasting.BroadcastRequest;
import com.microrisc.simply.iqrf.dpa.broadcasting.BroadcastResult;
import com.microrisc.simply.iqrf.dpa.protocol.DPA_ProtocolProperties;
import com.microrisc.simply.iqrf.dpa.v22x.devices.Coordinator;
import com.microrisc.simply.iqrf.dpa.v22x.devices.FRC;
import com.microrisc.simply.iqrf.dpa.v22x.di_services.method_id_transformers.CoordinatorStandardTransformer;
import com.microrisc.simply.iqrf.dpa.v22x.di_services.method_id_transformers.FRCStandardTransformer;
import com.microrisc.simply.iqrf.dpa.v22x.typeconvertors.DPA_ConfirmationConvertor;
import com.microrisc.simply.iqrf.dpa.v22x.types.DPA_Confirmation;
import com.microrisc.simply.iqrf.dpa.v22x.protocol.timing.TimingParamsStorage;
import com.microrisc.simply.network.BaseNetworkData;
import com.microrisc.simply.protocol.AbstractProtocolLayer;
import com.microrisc.simply.protocol.CallRequestComparator;
import com.microrisc.simply.protocol.MessageConvertor;
import com.microrisc.simply.protocol.SimpleRequestToResponseMatcher;
import com.microrisc.simply.typeconvertors.ValueConversionException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.microrisc.simply.iqrf.dpa.v22x.init.NetworkInfo;

/**
 * Protocol layer based on DPA_ProtocolProperties of IQRF.
 * 
 * @author <NAME>
 * @author <NAME>
 */
//JUNE-2015 - improved determing and using RF mode
public final class DPA_ProtocolLayer 
extends AbstractProtocolLayer
implements ProtocolStateMachineListener
{
    /** Logger. */
    private static final Logger logger = LoggerFactory.getLogger(DPA_ProtocolLayer.class);
    
    
    
    
    /**
     * Binds sent requests with theirs time of sending.
     */
    private static class TimeRequest {
        // sent request
        CallRequest request;
        
        // time, at which the request was sent
        long sentTime;
        
        TimeRequest(CallRequest request, long sentTime) {
            this.request = request;
            this.sentTime = sentTime;
        }
        
        public String toString() {
            StringBuilder strBuilder = new StringBuilder();
            String NEW_LINE = System.getProperty("line.separator");

            strBuilder.append(this.getClass().getSimpleName() + " { " + NEW_LINE);
            strBuilder.append(" Request: " + request + NEW_LINE);
            strBuilder.append(" Sent: " + sentTime + NEW_LINE);
            strBuilder.append("}");

            return strBuilder.toString();
        }
    }
    
    // information about potentionally time unlimited request - i.e. request,
    // whose response time is not inherently bounded, i.e. discovery
    private static class TimeUnlimitedRequestInfo {
        Class devIface;
        Set<String> methodIds;
        
        public TimeUnlimitedRequestInfo(Class devIface, Set<String> methodIds) {
            this.devIface = devIface;
            this.methodIds = methodIds;
        }
    }
    
    // map of time unlimited requests
    private static Map<Class, TimeUnlimitedRequestInfo> timeUnlimitedRequestsMap = new HashMap<>();
    
    // initialize set of time unlimited requests
    private static void initTimeUnlimitedRequests() {
        Set<String> coordUnlimitedOperations = new HashSet<>();
        coordUnlimitedOperations.add(
                CoordinatorStandardTransformer
                .getInstance()
                .transform(Coordinator.MethodID.RUN_DISCOVERY)
        );
        
        coordUnlimitedOperations.add(
                CoordinatorStandardTransformer
                .getInstance()
                .transform(Coordinator.MethodID.BOND_NODE)
        );
        
        timeUnlimitedRequestsMap.put(
                Coordinator.class,
                new TimeUnlimitedRequestInfo(
                        Coordinator.class,
                        coordUnlimitedOperations
                )
        );
        
        /*
        Set<String> frcUnlimitedOperations = new HashSet<>();
        frcUnlimitedOperations.add(
                FRCStandardTransformer
                .getInstance()
                .transform(FRC.MethodID.SEND)
        );

      
        frcUnlimitedOperations.add(
                FRCStandardTransformer
                .getInstance()
                .transform(FRC.MethodID.EXTRA_RESULT)
        );

        
        timeUnlimitedRequestsMap.put(
                FRC.class,
                new TimeUnlimitedRequestInfo(
                        FRC.class,
                        frcUnlimitedOperations
                )
        );
        */
    }
    
    // static initializer
    static {
        initTimeUnlimitedRequests();
    }   
    
    // indicates, wheather the specified request is time unlimited
    private static boolean isTimeUnlimitedRequest(CallRequest request) {
        TimeUnlimitedRequestInfo unlimRequestInfo 
                = timeUnlimitedRequestsMap.get(request.getDeviceInterface());
        
        if ( unlimRequestInfo == null ) {
            return false;
        }
        
        return unlimRequestInfo.methodIds.contains(request.getMethodId());        
    }

    // indicates, wheather a timeout is defined by user
    private static boolean isTimeoutDefinedByUserRequest(long procTime) {
        return procTime != WaitingTimeoutService.UNLIMITED_WAITING_TIMEOUT;
    }
    
    // indicates, wheather a time unlimited request is in process
    private volatile boolean isTimeUnlimitedRequestInProcess = false;
    
    // indicates, wheather a timeout is defined by user
    private volatile boolean isTimeoutDefinedByUserRequestInProcess = false;
    
    /** Last sent request. */
    private TimeRequest lastRequest = null;
    
    /** List of all requests, which was sent to network layer. */
    private List<TimeRequest> sentRequests = new LinkedList<>();
    
    /** Synchronization object for {@code sentRequest} data structure. */
    private final Object synchroSentRequest = new Object();
   
    // timing parameters manager
{'fraction_non_alphanumeric': 0.08059877108118708, 'fraction_numerical': 0.0042489214276376, 'mean_word_length': 2.7278265107212474, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, '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': '3529632', 'n_tokens_mistral': 4293, 'n_tokens_neox': 4211, 'n_words': 921}