PartialVisitIdProxy.java :  » J2EE » myfaces-core-2.0.0 » org » apache » myfaces » component » visit » Java Open Source

Java Open Source » J2EE » myfaces core 2.0.0 
myfaces core 2.0.0 » org » apache » myfaces » component » visit » PartialVisitIdProxy.java
/*
 * 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.myfaces.component.visit;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.faces.context.FacesContext;

/**
 * @author Werner Punz (latest modification by $Author: lu4242 $)
 * @version $Rev: 881558 $ $Date: 2009-11-17 16:55:58 -0500 (Tue, 17 Nov 2009) $
 *
 * A proxying class for our partial visit id handling
 * we need this class because
 * a) PartialVisitContext.getIds must return
 *  a valid modifyable set of client ids
 * 
 * b) There are some speed improvements like an
 *  inverse index, which need to change as well
 *  if the ids are changed!
 */
class PartialVisitIdProxy implements Set<String>{

    FacesContext _facesContext;
    Set<String> _ids;
    Map<String, Collection<String>> _inverseCache = new HashMap<String, Collection<String>>();
    Set<String> _forcedIds = new HashSet<String>();
    char _separatorChar;

    public Set<String> getIds() {
        return _ids;
    }

    public Set<String> getForcedIds() {
        return _forcedIds;
    }

    public Map<String, Collection<String>> getInverseCache() {
        return _inverseCache;
    }

    /**
     * Partial visit id proxy constructor
     * @param separatorChar the separator char for the reverse indexing
     * ie: ':' means view1:view2:component the ':' will be used for splitting
     * which is the standard char for now according to the specs
     *
     * @param ids a set of ids client ids to be processed
     */
    public PartialVisitIdProxy(char separatorChar, Collection<String> ids) {
        _ids = new HashSet<String>(ids);
        _separatorChar = separatorChar;
        initCaches();
    }

    private void removeFromIndex(String clientId) {
        char[] ids = clientId.toCharArray();
        
        StringBuilder finalContainer = new StringBuilder(clientId.length());
        for (int cnt = 0; cnt < ids.length; cnt++) {
            if (ids[cnt] == _separatorChar) {
                String containerName = finalContainer.toString();
                Collection<String> cacheEntry = _inverseCache.get(containerName);
                if (cacheEntry == null) {
                    continue;
                }
                if (cacheEntry.contains(clientId)) {
                    cacheEntry.remove(clientId);
                    if (cacheEntry.isEmpty()) {
                        _inverseCache.remove(containerName);
                    }
                }
            }
            finalContainer.append(ids[cnt]);
        }
        _forcedIds.remove(clientId);
    }


    private boolean addToIndex(String clientId) {
        
        //we do not use a split here because we cannot rely on regexps in case of unknown chars
        char[] ids = clientId.toCharArray();
        StringBuilder finalContainer = new StringBuilder(clientId.length());
        boolean added = false;
        for (int cnt = 0; cnt < ids.length; cnt++) {
            if (ids[cnt] == _separatorChar) {
                String containerName = finalContainer.toString();
                Collection<String> cacheEntry = _inverseCache.get(containerName);
                if (cacheEntry == null) {
                    cacheEntry = new HashSet<String>();
                    _inverseCache.put(containerName, cacheEntry);
                }
                cacheEntry.add(clientId);
                added = true;
            } 
            finalContainer.append(ids[cnt]);
        }
        //if not added add the id to the deep scan ids!
        if (!added) {
           return _forcedIds.add(clientId);
        }
        return true;
    }

    /**
     * we have to initialize our caches
     */
    private void initCaches() {
        _inverseCache.clear();
        _forcedIds.clear();

        for (String clientId : _ids) {
            addToIndex(clientId);
        }
    }

    public int size() {
        return _ids.size();
    }

    public boolean isEmpty() {
        return _ids.isEmpty();
    }

    public boolean contains(Object o) {
        return _ids.contains(o);
    }

    public Iterator<String> iterator() {
        return new ProxyingIterator(_ids.iterator());
    }

    public Object[] toArray() {
        return _ids.toArray();
    }

    public <T> T[] toArray(T[] a) {
        return _ids.toArray(a);
    }

    public boolean add(String o) {
        if(!_ids.add(o)) {
            return false;
        }
        return addToIndex(o);
    }

    public boolean remove(Object o) {
        if(!_ids.remove((String)o)) {
            return false;
        }
        removeFromIndex((String)o);
        return true;
    }

    public boolean containsAll(Collection<?> c) {
        return _ids.containsAll(c);
    }

    public boolean addAll(Collection<? extends String> c) {
        for(String element: c) {
            if(_ids.add(element)) {
                addToIndex(element);
            }
        }
        return true;
    }

    public boolean retainAll(Collection<?> c) {
        _ids = new HashSet<String>();

        for(Object element: c) {
            _ids.add((String)element);
        }
       initCaches();
        return true;
    }

    public boolean removeAll(Collection<?> c) {
        for(Object element: c) {
            remove(element);
        }
        return true;
    }

    public void clear() {
       _ids.clear();
       _forcedIds.clear();
       _inverseCache.clear();
    }

    class ProxyingIterator implements Iterator<String> {

        Iterator<String> _delegate = null;
        String _currentValue = null;

        public ProxyingIterator(Iterator delegate) {
            _delegate = delegate;
        }

        public boolean hasNext() {
            return _delegate.hasNext();
        }

        public String next() {
            _currentValue =  _delegate.next();
            return _currentValue;
        }

        public void remove() {
           
            _delegate.remove();
            removeFromIndex(_currentValue);
        }

    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.