/*
 * 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.felix.framework;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.List;
import javax.crypto.spec.IvParameterSpec;
import org.apache.felix.framework.capabilityset.Attribute;
import org.apache.felix.framework.capabilityset.Capability;
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.capabilityset.Directive;
import org.apache.felix.framework.capabilityset.SimpleFilter;
import org.apache.felix.framework.resolver.Module;
import org.apache.felix.framework.util.StringMap;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;

public class FilterImpl implements Filter
{
    private final SimpleFilter m_filter;

    public FilterImpl(String filterStr) throws InvalidSyntaxException
    {
        try
        {
            m_filter = SimpleFilter.parse(filterStr);
        }
        catch (Throwable th)
        {
            throw new InvalidSyntaxException(th.getMessage(), filterStr);
        }
    }

    public boolean match(ServiceReference sr)
    {
        return CapabilitySet.matches(new ServiceReferenceCapability(sr), m_filter);
    }

    public boolean match(Dictionary dctnr)
    {
        return CapabilitySet.matches(new DictionaryCapability(dctnr, false), m_filter);
    }

    public boolean matchCase(Dictionary dctnr)
    {
        return CapabilitySet.matches(new DictionaryCapability(dctnr, true), m_filter);
    }

    public boolean equals(Object o)
    {
        return toString().equals(o.toString());
    }

    public int hashCode()
    {
        return toString().hashCode();
    }

    public String toString()
    {
        return m_filter.toString();
    }

    static class DictionaryCapability implements Capability
    {
        private final StringMap m_map;
        private final Dictionary m_dict;

        public DictionaryCapability(Dictionary dict, boolean caseSensitive)
        {
            if (!caseSensitive)
            {
                m_dict = null;
                m_map = new StringMap(caseSensitive);
                if (dict != null)
                {
                    Enumeration keys = dict.keys();
                    while (keys.hasMoreElements())
                    {
                        Object key = keys.nextElement();
                        if (m_map.get(key) == null)
                        {
                            m_map.put(key, new Attribute((String) key, dict.get(key), false));
                        }
                        else
                        {
                            throw new IllegalArgumentException(
                                "Duplicate attribute: " + key.toString());
                        }
                    }
                }
            }
            else
            {
                m_map = null;
                m_dict = dict;
            }
        }

        public Module getModule()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String getNamespace()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Directive getDirective(String name)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<Directive> getDirectives()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Attribute getAttribute(String name)
        {
            if (m_map != null)
            {
                return (Attribute) m_map.get(name);
            }

            Object value = m_dict.get(name);
            return (value == null) ? null : new Attribute(name, value, false);
        }

        public List<Attribute> getAttributes()
        {
            return new ArrayList();
        }

        public List<String> getUses()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    static class ServiceReferenceCapability implements Capability
    {
        private final ServiceReference m_sr;

        public ServiceReferenceCapability(ServiceReference sr)
        {
            m_sr = sr;
        }

        public Module getModule()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String getNamespace()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Directive getDirective(String name)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public List<Directive> getDirectives()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Attribute getAttribute(String name)
        {
            Object value = m_sr.getProperty(name);
            return (value == null) ? null : new Attribute(name, value, false);
        }

        public List<Attribute> getAttributes()
        {
            return new ArrayList();
        }

        public List<String> getUses()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
}

@@ -952,50 +952,8 @@
 st;%0A
-import javax.crypto.spec.IvParameterSpec;%0A
 impo
@@ -2770,32 +2770,59 @@
 tive)%0A        %7B%0A
+            m_dict = dict;%0A
             if (
@@ -2855,39 +2855,8 @@
   %7B%0A
-                m_dict = null;%0A
     
@@ -2889,28 +2889,20 @@
 ringMap(
-caseSensitiv
+fals
 e);%0A    
@@ -3256,57 +3256,11 @@
 ey, 
-new Attribute((String) key, dict.get(key), false)
+key
 );%0A 
@@ -3623,39 +3623,8 @@
 ll;%0A
-                m_dict = dict;%0A
     
@@ -4250,32 +4250,146 @@
 name)%0A        %7B%0A
+            String key = name;%0A            Object value = null;%0A            if (m_dict != null)%0A            %7B%0A    
             if (
@@ -4395,32 +4395,36 @@
 (m_map != null)%0A
+    
             %7B%0A  
@@ -4441,25 +4441,25 @@
     
-return (Attribute
+    key = (String
 ) m_
@@ -4477,34 +4477,37 @@
 e);%0A            
+    
 %7D
-%0A
 %0A            Obj
@@ -4495,38 +4495,35 @@
   %7D%0A            
-Object
+   
  value = m_dict.
@@ -4522,30 +4522,43 @@
  m_dict.get(
-name);
+key);%0A            %7D
 %0A           
@@ -4596,36 +4596,35 @@
 : new Attribute(
-name
+key
 , value, false);
@@ -6103,9 +6103,8 @@
 %0A    %7D%0A%7D
-%0A

Improve handling of case insensitive keys. (FELIX-2039)