package org.griphyn.vdl.mapping;

import java.util.Map;
import java.util.Iterator;

import org.griphyn.vdl.karajan.VDL2FutureException;
import org.griphyn.vdl.type.Field;
import org.griphyn.vdl.type.Type;

public class RootArrayDataNode extends ArrayDataNode implements DSHandleListener {

	private boolean initialized=false;
	private Mapper mapper;
	private Map params;

	/**
	 * Instantiate a root array data node with specified type.
	 */
	public RootArrayDataNode(Type type) {
		super(Field.Factory.newInstance(), null, null);
		getField().setType(type);
	}

	public void init(Map params) {
		this.params = params;
		if(this.params == null) {
			initialized();
		} else {
			innerInit();
		}
	}

	private synchronized void innerInit() {
		Iterator i = params.entrySet().iterator();
		while(i.hasNext()) {
			Map.Entry entry = (Map.Entry) i.next();
			Object v = entry.getValue();
			if(v instanceof DSHandle && !( (DSHandle)v).isClosed()) {
				DSHandle dh = (DSHandle)v;
				dh.addListener(this);
				return;
			}
		}
		String desc = (String) params.get("descriptor");
		if (desc == null) {
			initialized();
			return;
		}
		try {
			mapper = MapperFactory.getMapper(desc, params);
			checkInputs();
			getField().setName(PARAM_PREFIX.getStringValue(mapper));
			initialized();
		}
		catch (InvalidMapperException e) {
			throw new RuntimeException(e);
		}
		if (isClosed()) {
		    notifyListeners();
		}
	}

	private void checkInputs() {
		try {
			RootDataNode.checkInputs(params, mapper, this);
		}
		catch (VDL2FutureException e) {
			e.getHandle().addListener(this);
		}
		catch (DependentException e) {
			setValue(new MappingDependentException(this, e));
			closeShallow();
		}
		initialized();
	}

	public void handleClosed(DSHandle handle) {
		innerInit();
	}

	public String getParam(String name) {
		if (params == null) {
			return null;
		}
		return (String) params.get(name);
	}

	public DSHandle getRoot() {
		return this;
	}

	public DSHandle getParent() {
		return null;
	}

	public Mapper getMapper() {
		if(initialized) {
			return mapper;
		} else {
			throw new VDL2FutureException(this);
		}
	}

	public boolean isArray() {
		return true;
	}

        public void setValue(Object value) {
                super.setValue(value);
                initialized();
        }

        private void initialized() {
                initialized=true;
        }

}

@@ -322,17 +322,19 @@
 tialized
-=
+ = 
 false;%0D%0A
@@ -379,16 +379,55 @@
 params;%0D
+%0A%09private DSHandle waitingMapperParam;%0D
 %0A%0D%0A%09/**%0D
@@ -682,16 +682,17 @@
 s;%0D%0A%09%09if
+ 
 (this.pa
@@ -727,24 +727,28 @@
 zed();%0D%0A%09%09%7D 
+%0D%0A%09%09
 else %7B%0D%0A%09%09%09i
@@ -965,16 +965,17 @@
 ;%0D%0A%09%09%09if
+ 
 (v insta
@@ -994,17 +994,16 @@
 le && !(
- 
 (DSHandl
@@ -1004,16 +1004,17 @@
 SHandle)
+ 
 v).isClo
@@ -1031,19 +1031,26 @@
 %09%09%09%09
-DSHandle dh
+waitingMapperParam
  = (
@@ -1062,16 +1062,17 @@
 dle)
+ 
 v;%0D%0A%09%09%09%09
 dh.a
@@ -1071,10 +1071,26 @@
 %09%09%09%09
-dh
+waitingMapperParam
 .add
@@ -2165,16 +2165,29 @@
 %09public 
+synchronized 
 Mapper g
@@ -2204,16 +2204,17 @@
  %7B%0D%0A%09%09if
+ 
 (initial
@@ -2244,17 +2244,20 @@
 er;%0D%0A%09%09%7D
- 
+%0D%0A%09%09
 else %7B%0D%0A
@@ -2254,25 +2254,71 @@
 %09%09else %7B%0D%0A%09%09
-%09
+    assert(waitingMapperParam != null);%0D%0A%09%09    
 throw new VD
@@ -2335,20 +2335,34 @@
 ception(
-this
+waitingMapperParam
 );%0D%0A%09%09%7D%0D
@@ -2415,28 +2415,24 @@
 rue;%0D%0A%09%7D%0D%0A%0D%0A
-    
     public v
@@ -2469,24 +2469,16 @@
         
- 
-       
 super.se
@@ -2497,32 +2497,24 @@
 );%0D%0A        
- 
-       
 initialized(
@@ -2525,21 +2525,13 @@
     
- 
-   
 %7D%0D%0A%0D%0A
-    
     
@@ -2568,24 +2568,16 @@
         
- 
-       
 initiali
@@ -2579,17 +2579,19 @@
 tialized
-=
+ = 
 true;%0D%0A 
@@ -2593,20 +2593,14 @@
 e;%0D%0A    
-    %7D%0D%0A
+%7D
 %0D%0A%7D%0D%0A

make dependence on future mapper params direct