All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.jaxx.runtime.context.DefaultJAXXContext Maven / Gradle / Ivy

There is a newer version: 3.0-alpha-6
Show newest version
/*
 * #%L
 * JAXX :: Runtime
 * %%
 * Copyright (C) 2008 - 2017 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nuiton.jaxx.runtime.context;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.jaxx.runtime.JAXXContext;
import org.nuiton.jaxx.runtime.JAXXObject;
import org.nuiton.jaxx.runtime.JAXXUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * The default {@link JAXXContext} to be used in a {@link JAXXObject} by
 * delegation.
 *
 * The values are store in a {@link Map} but we can not use directly the values
 * as key.
 *
 * Because, it does not work if we add for the same object multi entries (named
 * and unamed)...
 *
 * We prefer use as entry the {@link JAXXContextEntryDef} associated with the
 * value.
 *
 * @author Tony Chemit - [email protected]
 */
public class DefaultJAXXContext implements JAXXContext {

    /** entry of the parent context */
    protected static final JAXXContextEntryDef
            PARENT_CONTEXT_ENTRY = JAXXUtil.newContextEntryDef(JAXXContext.class);

    /** Logger */
    static private final Log log = LogFactory.getLog(DefaultJAXXContext.class);

    /** le context parent */
    protected JAXXContext parentContext;

    /** les données contenues dans le context */
    protected final Map, Object> data;

    public DefaultJAXXContext() {
        data = new HashMap<>();
    }

    @Override
    public  void setContextValue(T o) {
        setContextValue(o, null);
    }

    @Override
    public  void setContextValue(T o, String name) {
        if (name == null && PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) {
            setParentContext((JAXXContext) o);
            return;
        }
        JAXXContextEntryDef entry = getKey(name, o.getClass());
        // first remove entry
        Object oldValue = remove0(o.getClass(), name);
        if (oldValue != null) {
            if (log.isDebugEnabled()) {
                log.debug("remove value " + oldValue.getClass() + " for " +
                                  entry);
            }
        }
        // then can put safely
        data.put(entry, o);
    }

    @Override
    public  T getContextValue(Class clazz) {
        return getContextValue(clazz, null);
    }

    @SuppressWarnings({"unchecked"})
    @Override
    public  T getContextValue(Class clazz, String name) {
        if (parentContext != null &&
                parentContext.getClass().equals(clazz) ||
                PARENT_CONTEXT_ENTRY.accept(clazz, name)) {
            return (T) getParentContext();
        }
        for (Entry, Object> entry : data.entrySet()) {
            if (entry.getKey().accept(clazz, name)) {
                return (T) entry.getValue();
            }
        }

        // no value found in this context, will try in the parent context
        if (JAXXContext.class.equals(clazz)) {
            // no seek in the parent context, since we are already looking
            // for it
            return null;
        }

        JAXXContext parent = getParentContext();
        if (parent == null) {
            // no parent context, so no value find
            return null;
        }
        // seek in parent context
        return parent.getContextValue(clazz, name);
    }

    @Override
    public  void removeContextValue(Class klazz) {
        removeContextValue(klazz, null);
    }

    @Override
    public  void removeContextValue(Class klazz, String name) {
        remove0(klazz, name);
    }

    /**
     * Obtain all the keys of data for a given type.
     *
     * @param klass the type of searched keys
     * @return the array of all names of keys for the given type of data
     * @since 1.3
     */
    public String[] getKeys(Class klass) {
        List keys = new ArrayList<>();
        for (JAXXContextEntryDef key : data.keySet()) {
            if (key.getKlass().equals(klass)) {
                keys.add(key.getName());
            }
        }
        return keys.toArray(new String[keys.size()]);

    }

    public void clear() {
        data.clear();
    }

    protected JAXXContextEntryDef getKey(String name, Class klass) {
        //FIXME-TC20100322 : must change this to have a store, we instanciate
        // a new object each time we wants to deal with the context...
        return JAXXUtil.newContextEntryDef(name, klass);
    }

    @SuppressWarnings({"unchecked"})
    protected  T remove0(Class klass, String name) {
        if (PARENT_CONTEXT_ENTRY.accept(klass, name)) {
            JAXXContext old = getParentContext();
            setParentContext(null);
            return (T) old;
        }
        JAXXContextEntryDef entry = getEntry(klass, name);
//        JAXXContextEntryDef entry = null;
//        for (JAXXContextEntryDef entryDef : data.keySet()) {
//            if (entryDef.accept(klass, name)) {
//                entry = entryDef;
//                break;
//            }
//        }
        if (entry != null) {
            return (T) data.remove(entry);
        }

        if (JAXXContext.class.equals(klass)) {
            return null;
        }

        // try on parent
        JAXXContext parent = getParentContext();

        if (parent == null) {
            // no parent, stop now, can not found entry
            return null;
        }

        if (parent instanceof DefaultJAXXContext) {
            // try now on the parent
            return ((DefaultJAXXContext) parent).remove0(klass, name);
        }

        // can not find the entry anywhere, so says that nothing was removed
        return null;
    }

    protected JAXXContextEntryDef getEntry(Class klass, String name) {
        JAXXContextEntryDef entry = null;
        for (JAXXContextEntryDef entryDef : data.keySet()) {
            if (entryDef.accept(klass, name)) {
                entry = entryDef;
                break;
            }
        }
        return entry;
    }

    protected JAXXContext getParentContext() {
        return parentContext;
    }

    protected void setParentContext(JAXXContext parentContext) {
        if (parentContext instanceof JAXXObject) {
            // keep the real context, not the ui
            parentContext = ((JAXXObject) parentContext).getDelegateContext();
        }
        this.parentContext = parentContext;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy