/**************************************************************
 * 
 * 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 com.sun.star.lib.uno.environments.java;

import com.sun.star.uno.IEnvironment;
import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Iterator;

/**
 * The java_environment is the environment where objects and
 * interfaces are registered, which are mapped out of java or
 * into java.
 *
 * <p>The java_environment implements the <code>IEnvironment</code> interface
 * defined in the uno runtime.</p>
 *
 * @see com.sun.star.uno.UnoRuntime
 * @see com.sun.star.uno.IEnvironment
 * @since UDK1.0
 */
public final class java_environment implements IEnvironment {
    public java_environment(Object context) {
        this.context = context;
    }

    // @see com.sun.star.uno.IEnvironment#getContext
    public Object getContext() {
        return context;
    }

    // @see com.sun.star.uno.IEnvironment#getName
    public String getName() {
        return "java";
    }

    // @see com.sun.star.uno.IEnvironment#registerInterface
    public Object registerInterface(Object object, String[] oid, Type type) {
        if (oid[0] == null) {
            oid[0] = UnoRuntime.generateOid(object);
        }
        return (isProxy(object) ? proxies : localObjects).register(
            object, oid[0], type);
    }

    /**
     * You have to revoke ANY interface that has been registered via this
     * method.
     *
     * @param oid object id of interface to be revoked
     * @param type the type description of the interface
     * @see com.sun.star.uno.IEnvironment#revokeInterface
     */
    public void revokeInterface(String oid, Type type) {
        if (!proxies.revoke(oid, type)) {
            localObjects.revoke(oid, type);
        }
    }

    /**
     * Retrieves an interface identified by its object id and type from this
     * environment.
     *
     * @param oid object id of interface to be retrieved
     * @param type the type description of the interface to be retrieved
     * @see com.sun.star.uno.IEnvironment#getRegisteredInterface
     */
    public Object getRegisteredInterface(String oid, Type type) {
        Object o = proxies.get(oid, type);
        if (o == null) {
            o = localObjects.get(oid, type);
        }
        return o;
    }

    /**
     * Retrieves the object identifier for a registered interface from this
     * environment.
     *
     * @param object a registered interface
     * @see com.sun.star.uno.IEnvironment#getRegisteredObjectIdentifier
     */
    public String getRegisteredObjectIdentifier(Object object) {
        return UnoRuntime.generateOid(object);
    }

    // @see com.sun.star.uno.IEnvironment#list
    public void list() {
// TODO???
//      synchronized (proxies) {
//          System.err.println("##### " + getClass().getName() + ".list: "
//                             + getName() + ", " + getContext());
//          for (Iterator it = proxies.values().iterator(); it.hasNext();) {
//              System.err.println("#### entry: " + it.next());
//          }
//      }
    }

    /**
     * Revokes all registered proxy interfaces.
     *
     * <p>This method should be part of <code>IEnvironment</code>.  It is called
     * from <code>com.sun.star.lib.uno.bridges.java_remote.<!--
     * -->java_remote_bridge.dispose</code>.</p>
     */
    public void revokeAllProxies() {
        proxies.clear();
    }

    // TODO  What's this???  java.lang.Object#equals requires reflexivity...
    //
    // Maybe this was hacked in so that different bridges use different
    // instances of java_environment.  That is desirable for the following
    // reason:  An OID is bridged in over bridge A, a proxy is created on the
    // Java side, and recorded in the java_environment.  The same OID is then
    // bridged in over another bridge B.  If there were only one
    // java_environment shared by both bridges, the proxy from bridge A would be
    // reused.  If now bridge A is taken down programatically (e.g., because
    // some controlling code somehow deduced that no objects are mapped over
    // that bridge any longer), but the proxy is still used by bridge B, using
    // the proxy would now result in errors.  The explicit API to control
    // bridges forbids to transparently share proxies between bridges, and using
    // different java_environment instances for different bridges is the way to
    // enforce this.
    public boolean equals(Object obj) {
        return false;
    }

    private static final class Registry {
        public synchronized Object register(
            Object object, String oid, Type type)
        {
            cleanUp();
            Level1Entry l1 = level1map.get(oid);
            if (l1 != null) {
                Level2Entry l2 = l1.level2map.get(type);
                if (l2 != null) {
                    Object o = l2.get();
                    if (o != null) {
                        l2.acquire();
                        return o;
                    }
                }
            }
            // TODO  If a holder references an unreachable object, but still has
            // a positive count, it is replaced with a new holder (referencing a
            // reachable object, and with a count of 1).  Any later calls to
            // revoke that should decrement the count of the previous holder
            // would now decrement the count of the new holder, removing it
            // prematurely.  This is a design flaw that will be fixed when
            // IEnvironment.revokeInterface is changed to no longer use
            // counting.  (And this problem is harmless, as currently a holder
            // either references a strongly held object and uses register/revoke
            // to control it, or references a weakly held proxy and never
            // revokes it.)
            if (l1 == null) {
                l1 = new Level1Entry();
                level1map.put(oid, l1);
            }
            l1.level2map.put(type, new Level2Entry(oid, type, object, queue));
            return object;
        }

        public synchronized boolean revoke(String oid, Type type) {
            Level1Entry l1 = level1map.get(oid);
            Level2Entry l2 = null;
            if (l1 != null) {
                l2 = l1.level2map.get(type);
                if (l2 != null && l2.release()) {
                    removeLevel2Entry(l1, oid, type);
                }
            }
            cleanUp();
            return l2 != null;
        }

        public synchronized Object get(String oid, Type type) {
            Level1Entry l1 = level1map.get(oid);
            return l1 == null ? null : l1.find(type);
        }

        public synchronized void clear() {
            level1map.clear();
            cleanUp();
        }

        // must only be called while synchronized on this Registry:
        private void cleanUp() {
            for (;;) {
                Level2Entry l2 = (Level2Entry) queue.poll();
                if (l2 == null) {
                    break;
                }
                // It is possible that a Level2Entry e1 for the OID/type pair
                // (o,t) becomes weakly reachable, then another Level2Entry e2
                // is registered for the same pair (o,t) (a new Level2Entry is
                // created since now e1.get() == null), and only then e1 is
                // enqueued.  To not erroneously remove the new e2 in that case,
                // check whether the map still contains e1:
                Level1Entry l1 = level1map.get(l2.oid);
                if (l1 != null && l1.level2map.get(l2.type) == l2) {
                    removeLevel2Entry(l1, l2.oid, l2.type);
                }
            }
        }

        // must only be called while synchronized on this Registry:
        private void removeLevel2Entry(Level1Entry l1, String oid, Type type) {
            l1.level2map.remove(type);
            if (l1.level2map.isEmpty()) {
                level1map.remove(oid);
            }
        }

        private static final class Level1Entry {
            // must only be called while synchronized on enclosing Registry:
            public Object find(Type type) {
                // First, look for an exactly matching entry; then, look for an
                // arbitrary entry for a subtype of the request type:
                Level2Entry l2 = level2map.get(type);
                if (l2 != null) {
                    Object o = l2.get();
                    if (o != null) {
                        return o;
                    }
                }
                for (Iterator<Level2Entry> i = level2map.values().iterator();
                     i.hasNext();)
                {
                    l2 = i.next();
                    if (type.isSupertypeOf(l2.type)) {
                        Object o = l2.get();
                        if (o != null) {
                            return o;
                        }
                    }
                }
                return null;
            }

            public final HashMap<Type, Level2Entry> level2map =
                new HashMap<Type, Level2Entry>();
        }

        private static final class Level2Entry extends WeakReference<Object> {
            public Level2Entry(
                String oid, Type type, Object object, ReferenceQueue queue)
            {
                super(object, queue);
                this.oid = oid;
                this.type = type;
            }

            // must only be called while synchronized on enclosing Registry:
            public void acquire() {
                ++count;
            }

            // must only be called while synchronized on enclosing Registry:
            public boolean release() {
                return --count == 0;
            }

            public final String oid;
            public final Type type;

            private int count = 1;
        }

        private final HashMap<String, Level1Entry> level1map =
            new HashMap<String, Level1Entry>();
        private final ReferenceQueue queue = new ReferenceQueue();
    }

    private boolean isProxy(Object object) {
        return object instanceof com.sun.star.lib.uno.Proxy;
    }

    private static final Registry localObjects = new Registry();

    private final Object context;
    private final Registry proxies = new Registry();
}
