docs: public static void setProperties(Object bean, Map<String,?> props, Class<? extends Annotation> tagCls) throws IntrospectionException, IllegalAccessException, InvocationTargetException, InstantiationException
  	{
  		Class<?> beanCls;
  		PropertyDescriptor[] descriptors;
  		Map<String,PropertyDescriptor> descriptorMap = new HashMap<String,PropertyDescriptor>();
  		Method meth;
  		String name;
  		Object value;
  		Class<?> propCls;
  		Class<?> valCls;
  
  		beanCls = bean.getClass();
  		if((descriptors = Introspector.getBeanInfo(beanCls).getPropertyDescriptors())==null)
  			throw new IllegalArgumentException("Unable to get PropertyDescriptors for class " + beanCls.getName() + '.');
  		for(PropertyDescriptor pd : descriptors)
  			descriptorMap.put(pd.getName(), pd);
  		for(Map.Entry<String,?> prop : props.entrySet())
  		{
  			name = prop.getKey();
  			value = prop.getValue();
  			PropertyDescriptor pd;
  
  			if((pd=descriptorMap.get(name))==null)
  				throw new IllegalArgumentException("Bean class " + beanCls.getName() + " does not have property " + name + '.');
  			if((meth=pd.getWriteMethod())==null)
  				throw new IllegalArgumentException("Bean class " + beanCls.getName() + " does not have a setter for property " + name + '.');
  			if((propCls = pd.getPropertyType())==null)
  				throw new IllegalArgumentException("Bean class " + beanCls.getName() + " does not have a type for property " + name + '.');
  			propCls = Reflections.wrapperIfPrimitive(propCls);
  			if(value==null)
  				valCls = propCls;
  			else
  				valCls = value.getClass();
  			if(!propCls.isAssignableFrom(valCls))
  			{
  				if(String.class.equals(valCls))
  				{
  					setPropertyAsText(bean, name, (String)value, pd, propCls, tagCls);
  					continue;
  				}
  				throw new IllegalArgumentException("Property " + name + " of class " + beanCls.getName() + " is of type " + propCls.getName() + " which is not assignable from " + valCls.getName() + '.');
  			}
  			if(tagCls!=null&&!meth.isAnnotationPresent(tagCls))
  				throw new IllegalArgumentException("Write method " + meth + " for property " + name + " of class " + bean.getClass() + " does not have annotation " + tagCls + '.');
  			meth.invoke(bean, prop.getValue());
  		}
  	}