/*
 * Copyright 2010 JBoss 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.drools.core.marshalling.impl;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

import org.kie.api.marshalling.ObjectMarshallingStrategy;
import org.kie.api.marshalling.ObjectMarshallingStrategyAcceptor;

public class IdentityPlaceholderResolverStrategy
    implements
    ObjectMarshallingStrategy {
    
    private Map<Integer, Object> ids;
    private Map<Object, Integer> objects;

    private ObjectMarshallingStrategyAcceptor acceptor;
    
    public IdentityPlaceholderResolverStrategy(ObjectMarshallingStrategyAcceptor acceptor) {
        this.acceptor = acceptor;
        this.ids = new HashMap<Integer, Object>();
        this.objects = new IdentityHashMap<Object, Integer>();
    }

    public Object read(ObjectInputStream os) throws IOException,
                                                       ClassNotFoundException {
        int id = os.readInt();
        return  ids.get( id );
    }

    public void write(ObjectOutputStream os,
                      Object object) throws IOException {
        Integer id = ( Integer ) objects.get( object );
        if ( id == null ) {
            id = ids.size();
            ids.put( id, object );
            objects.put(  object, id );
        }
        os.writeInt( id );
    }

    public boolean accept(Object object) {
        return this.acceptor.accept( object );
    }

    public byte[] marshal(Context context,
                          ObjectOutputStream os,
                          Object object) {
        Integer id = ( Integer ) objects.get( object );
        if ( id == null ) {
            id = ids.size();
            ids.put( id, object );
            objects.put(  object, id );
        }
        return intToByteArray( id.intValue() );
    }

    public Object unmarshal(Context context,
                            ObjectInputStream is,
                            byte[] object, 
                            ClassLoader classloader ) {
        return ids.get( byteArrayToInt( object ) );
    }
    
    private final byte[] intToByteArray(int value) {
        return new byte[] {
                (byte) ((value >>> 24) & 0xFF),
                (byte) ((value >>> 16) & 0xFF),
                (byte) ((value >>> 8) & 0xFF),
                (byte) (value  & 0xFF) };
    }    
    
    private final int byteArrayToInt(byte [] b) {
        return (b[0] << 24)
                + ((b[1] & 0xFF) << 16)
                + ((b[2] & 0xFF) << 8)
                + (b[3] & 0xFF);
    }
    
    public Context createContext() {
        // no need for context
        return null;
    }

}

@@ -631,16 +631,141 @@
 .impl;%0A%0A
+import org.kie.api.marshalling.ObjectMarshallingStrategy;%0Aimport org.kie.api.marshalling.ObjectMarshallingStrategyAcceptor;%0A%0A
 import j
@@ -784,16 +784,16 @@
 eption;%0A
-
 import j
@@ -940,133 +940,8 @@
 p;%0A%0A
-import org.kie.api.marshalling.ObjectMarshallingStrategy;%0Aimport org.kie.api.marshalling.ObjectMarshallingStrategyAcceptor;%0A%0A
 publ
@@ -1032,21 +1032,17 @@
 ategy %7B%0A
-    
 %0A
+
     priv
@@ -1349,24 +1349,24 @@
  Object%3E();%0A
-
         this
@@ -1415,32 +1415,203 @@
 eger%3E();%0A    %7D%0A%0A
+    public IdentityPlaceholderResolverStrategy(ObjectMarshallingStrategyAcceptor acceptor, Map%3CInteger, Object%3E ids) %7B%0A        this(acceptor);%0A        setIds(ids);%0A    %7D%0A%0A
     public Objec
@@ -3464,10 +3464,327 @@
 %0A    %7D%0A%0A
+    public Map%3CInteger, Object%3E getIds() %7B%0A        return ids;%0A    %7D%0A%0A    public void setIds(Map%3CInteger, Object%3E ids) %7B%0A        this.ids = ids;%0A        objects.clear();%0A        for (Map.Entry%3CInteger, Object%3E idEntry : ids.entrySet()) %7B%0A            objects.put(idEntry.getValue(), idEntry.getKey());%0A        %7D%0A    %7D%0A
 %7D%0A

add accessors to ids map of IdentityPlaceholderResolverStrategy