/*
 * Copyright 2014 CyberVision, Inc.
 *
 * 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 org.kaaproject.kaa.server.operations.service.filter;

import java.util.LinkedList;
import java.util.List;

import org.kaaproject.kaa.common.dto.ProfileFilterDto;
import org.kaaproject.kaa.common.dto.ProfileSchemaDto;
import org.kaaproject.kaa.server.operations.service.cache.AppVersionKey;
import org.kaaproject.kaa.server.operations.service.cache.CacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.EvaluationException;
import org.springframework.stereotype.Service;

/**
 * Default implementation of {@link FilterService FilterService}.
 *
 * @author ashvayka
 */
@Service
public class DefaultFilterService implements FilterService {

    /** The Constant logger. */
    private static final Logger LOG = LoggerFactory.getLogger(DefaultFilterService.class);

    /** The cache service. */
    @Autowired
    private CacheService cacheService;

    /**
     * Instantiates a new default filter service.
     */
    public DefaultFilterService() {
        super();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.kaaproject.kaa.server.operations.service.filter.FilterService#
     * getAllMatchingFilters
     * (org.kaaproject.kaa.server.operations.service.cache.AppVersionKey,
     * java.lang.String)
     */
    @Override
    public List<ProfileFilterDto> getAllMatchingFilters(AppVersionKey appProfileVersionKey, String profileBody) {
        ProfileSchemaDto profileSchema = cacheService.getProfileSchemaByAppAndVersion(appProfileVersionKey);
        List<ProfileFilterDto> filters = cacheService.getFilters(appProfileVersionKey);
        LOG.trace("Found {} filters by {}", filters.size(), appProfileVersionKey);
        List<ProfileFilterDto> matchingFilters = new LinkedList<ProfileFilterDto>();
        Filter filter = null;
        for (ProfileFilterDto filterBody : filters) {
            if (filter == null) {
                filter = new DefaultFilter(filterBody.getBody(), profileSchema.getSchema());
            } else {
                filter.updateFilterBody(filterBody.getBody());
            }
            LOG.trace("matching profile body with filter {}", filter);
            try {
                if (filter.matches(profileBody)) {
                    matchingFilters.add(filterBody);
                    LOG.trace("profile body matched");
                }
            } catch (EvaluationException ee) {
                LOG.warn("Failed to process filter {} due to evaluate exception. Please check your filter body", filterBody.getBody(), ee);
            } catch (Exception e) {
                LOG.error("Failed to process filter {} due to exception", filterBody.getBody(), e);
            }
        }
        return matchingFilters;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.kaaproject.kaa.server.operations.service.filter.FilterService#matches
     * (java.lang.String, java.lang.String)
     */
    @Override
    public boolean matches(String appToken, String profileFilterId, String profileBody) {
        ProfileFilterDto filterDto = cacheService.getFilter(profileFilterId);
        AppVersionKey appProfileVersionKey = new AppVersionKey(appToken, filterDto.getMajorVersion());
        ProfileSchemaDto profileSchema = cacheService.getProfileSchemaByAppAndVersion(appProfileVersionKey);
        Filter filter = new DefaultFilter(filterDto.getBody(), profileSchema.getSchema());
        LOG.trace("matching profile body with filter {}", filter);
        return filter.matches(profileBody);
    }

}

@@ -3678,32 +3678,50 @@
  profileBody) %7B%0A
+        try %7B%0A    
         ProfileF
@@ -3782,16 +3782,20 @@
 terId);%0A
+    
         
@@ -3889,32 +3889,36 @@
 ion());%0A        
+ 
+   
 ProfileSchemaDto
@@ -4002,32 +4002,36 @@
 onKey);%0A        
+   
+ 
 Filter filter = 
@@ -4097,32 +4097,36 @@
 ema());%0A        
+    
 LOG.trace(%22match
@@ -4172,24 +4172,28 @@
 r);%0A        
+ 
+   
 return filte
@@ -4212,21 +4212,350 @@
 ofileBody);%0A
+        %7D catch (EvaluationException ee) %7B%0A            LOG.warn(%22Failed to process filter %7B%7D due to evaluate exception. Please check your filter body%22, profileFilterId, ee);%0A        %7D catch (Exception e) %7B%0A            LOG.error(%22Failed to process filter %7B%7D due to exception%22, profileFilterId, e);%0A        %7D%0A        return false;%0A
     %7D%0A%0A%7D%0A

fix profile filter evaluation for the removed profile filter