class ReflectionObjectModelResolver implements ObjectModelResolver {

	@Override
	public Object getInstance(ObjectModel model, ClassLoader cl, Map<String, Object> contextParams) {
		
		Class<?> clazz = getClassObject(model.getIdentifier(), cl);
		Object instance = null;
		InternalRuntimeManager manager = null;
		if (contextParams.containsKey("runtimeManager")) {
			manager = (InternalRuntimeManager) contextParams.get("runtimeManager");
			instance = manager.getCacheManager().get(clazz.getName());
			if (instance != null) {
				return instance;
			}
		}
		if (model.getParameters() == null || model.getParameters().isEmpty()) {
			logger.debug("About to create instance of {} with no arg constructor", model.getIdentifier());
			// no parameters then use no arg constructor
			try {
				instance = clazz.newInstance();
			} catch (Exception e) {
				throw new IllegalArgumentException("Unable to create instance (no arg constructor) of type "
									+ model.getIdentifier() + " due to " + e.getMessage(), e);
			}
		} else {
			logger.debug("About to create instance of {} with {} parameters", model.getIdentifier(), model.getParameters().size());
			// process parameter instances
			Class<?>[] parameterTypes = new Class<?>[model.getParameters().size()];
			Object[] paramInstances = new Object[model.getParameters().size()];
			
			int index = 0;
			for (Object param : model.getParameters()) {
				
				if (param instanceof ObjectModel) {
					logger.debug("Parameter is of type ObjectModel (id: {}), trying to create instance based on that model",
							((ObjectModel) param).getIdentifier());
					Class<?> paramclazz = getClassObject(((ObjectModel)param).getIdentifier(), cl);
					parameterTypes[index] = paramclazz;
					
					paramInstances[index] = getInstance(((ObjectModel)param), cl, contextParams);
				} else {
					if (contextParams.containsKey(param)) {
						logger.debug("Parametr references context parametr with name {}", param);
						Object contextValue = contextParams.get(param);
						Class<?> paramClass = contextValue.getClass();
						if (knownContextParamMapping.containsKey(param)) {
							paramClass = knownContextParamMapping.get(param);
						}
						parameterTypes[index] = paramClass;
						paramInstances[index] = contextValue;
					} else {
						logger.debug("Parameter is simple type (string) - {}", param);
						parameterTypes[index] = param.getClass();
						paramInstances[index] = param;
					}
				}
				
				index++;
			}
			try {	
				logger.debug("Creating instance of class {} with parameter types {} and parameter instances {}",
						clazz, parameterTypes, paramInstances);
				Constructor<?> constructor = clazz.getConstructor(parameterTypes);
				instance = constructor.newInstance(paramInstances);
			} catch (Exception e) {
				throw new IllegalArgumentException("Unable to create instance (" + parameterTypes + " constructor) of type "
									+ model.getIdentifier() + " due to " + e.getMessage(), e);
			}
		}
		logger.debug("Created instance : {}", instance);
		
		if (manager != null && instance instanceof Cacheable) {
			manager.getCacheManager().add(instance.getClass().getName(), instance);
		}
		return instance;
	}

	public  ReflectionObjectModelResolver();

}