⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 beanwrapper.java

📁  EasyDBO是一个超轻量级对象-关系映射(Object/Relation Mapping
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
				logger.debug("Using cached nested BeanWrapper for property '" + canonicalName + "'");
			}
		}
		return nestedBw;
	}

	/**
	 * Create a new nested BeanWrapper instance.
	 * <p>Default implementation creates a BeanWrapperImpl instance.
	 * Can be overridden in subclasses to create a BeanWrapperImpl subclass.
	 * @param object object wrapped by this BeanWrapper
	 * @param nestedPath the nested path of the object
	 * @return the nested BeanWrapper instance
	 */
	protected BeanWrapper newNestedBeanWrapper(Object object, String nestedPath) {
		return new BeanWrapper(object, nestedPath, this);
	}

	/**
	 * Parse the given property name into the corresponding property name tokens.
	 * @param propertyName the property name to parse
	 * @return representation of the parsed property tokens
	 */
	private PropertyTokenHolder getPropertyNameTokens(String propertyName) {
		PropertyTokenHolder tokens = new PropertyTokenHolder();
		String actualName = null;
		List keys = new ArrayList(2);
		int searchIndex = 0;
		while (searchIndex != -1) {
			int keyStart = propertyName.indexOf(PROPERTY_KEY_PREFIX, searchIndex);
			searchIndex = -1;
			if (keyStart != -1) {
				int keyEnd = propertyName.indexOf(PROPERTY_KEY_SUFFIX, keyStart + PROPERTY_KEY_PREFIX.length());
				if (keyEnd != -1) {
					if (actualName == null) {
						actualName = propertyName.substring(0, keyStart);
					}
					String key = propertyName.substring(keyStart + PROPERTY_KEY_PREFIX.length(), keyEnd);
					if ((key.startsWith("'") && key.endsWith("'")) || (key.startsWith("\"") && key.endsWith("\""))) {
						key = key.substring(1, key.length() - 1);
					}
					keys.add(key);
					searchIndex = keyEnd + PROPERTY_KEY_SUFFIX.length();
				}
			}
		}
		tokens.actualName = (actualName != null ? actualName : propertyName);
		tokens.canonicalName = tokens.actualName;
		if (!keys.isEmpty()) {
			tokens.canonicalName +=
					PROPERTY_KEY_PREFIX +
					StringUtils.collectionToDelimitedString(keys, PROPERTY_KEY_SUFFIX + PROPERTY_KEY_PREFIX) +
					PROPERTY_KEY_SUFFIX;
			tokens.keys = StringUtils.toStringArray(keys);
		}
		return tokens;
	}


	//---------------------------------------------------------------------
	// Implementation of PropertyAccessor interface
	//---------------------------------------------------------------------

	public Object getPropertyValue(String propertyName) throws BeansException {
		BeanWrapper nestedBw = getBeanWrapperForPropertyPath(propertyName);
		PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
		return nestedBw.getPropertyValue(tokens);
	}

	private Object getPropertyValue(PropertyTokenHolder tokens) throws BeansException {
		String propertyName = tokens.canonicalName;
		String actualName = tokens.actualName;
		PropertyDescriptor pd = getPropertyDescriptorInternal(tokens.actualName);
		if (pd == null || pd.getReadMethod() == null) {
			throw new NotReadablePropertyException(getRootClass(), this.nestedPath + propertyName);
		}
		Method readMethod = pd.getReadMethod();		
			logger.debug("About to invoke read method [" + readMethod + "] on object of class [" +
					this.object.getClass().getName() + "]");
	
		try {
			if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
				readMethod.setAccessible(true);
			}
			Object value = readMethod.invoke(this.object, (Object[]) null);
			
			if (tokens.keys != null) {
				// apply indexes and map keys
				for (int i = 0; i < tokens.keys.length; i++) {
					String key = tokens.keys[i];
					if (value == null) {
						throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
								"Cannot access indexed value of property referenced in indexed " +
								"property path '" + propertyName + "': returned null");
					}
					else if (value.getClass().isArray()) {
						value = Array.get(value, Integer.parseInt(key));
					}
					else if (value instanceof List) {
						List list = (List) value;
						value = list.get(Integer.parseInt(key));
					}
					else if (value instanceof Set) {
						// Apply index to Iterator in case of a Set.
						Set set = (Set) value;
						int index = Integer.parseInt(key);
						if (index < 0 || index >= set.size()) {
							throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
									"Cannot get element with index " + index + " from Set of size " +
									set.size() + ", accessed using property path '" + propertyName + "'");
						}
						Iterator it = set.iterator();
						for (int j = 0; it.hasNext(); j++) {
							Object elem = it.next();
							if (j == index) {
								value = elem;
								break;
							}
						}
					}
					else if (value instanceof Map) {
						Map map = (Map) value;
						Class mapKeyType = null;
						if (JdkVersion.getJavaVersion() >= JdkVersion.JDK_1_5) {
							mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod());
						}
						// IMPORTANT: Do not pass full property name in here - property editors
						// must not kick in for map keys but rather only for map values.
						Object convertedMapKey = this.typeConverterDelegate.convertIfNecessary(
								null, null, key, mapKeyType);
						// Pass full property name and old value in here, since we want full
						// conversion ability for map values.
						value = map.get(convertedMapKey);
					}
					else {
						throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
								"Property referenced in indexed property path '" + propertyName +
								"' is neither an array nor a List nor a Set nor a Map; returned value was [" + value + "]");
					}
				}
			}
			
			return value;
		}
		catch (InvocationTargetException ex) {
			throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
					"Getter for property '" + actualName + "' threw exception", ex);
		}
		catch (IllegalAccessException ex) {
			throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
					"Illegal attempt to get property '" + actualName + "' threw exception", ex);
		}
		catch (IndexOutOfBoundsException ex) {
			throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
					"Index of out of bounds in property path '" + propertyName + "'", ex);
		}
		catch (NumberFormatException ex) {
			throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
					"Invalid index in property path '" + propertyName + "'", ex);
		}
	}

	public void setPropertyValue(String propertyName, Object value) throws BeansException {
		BeanWrapper nestedBw = null;
		try {
			nestedBw = getBeanWrapperForPropertyPath(propertyName);
		}
		catch (NotReadablePropertyException ex) {
			throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
					"Nested property in path '" + propertyName + "' does not exist", ex);
		}
		PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
		nestedBw.setPropertyValue(tokens, value);
	}

	private void setPropertyValue(PropertyTokenHolder tokens, Object newValue) throws BeansException {
		String propertyName = tokens.canonicalName;
		if (tokens.keys != null) {
			// Apply indexes and map keys: fetch value for all keys but the last one.
			PropertyTokenHolder getterTokens = new PropertyTokenHolder();
			getterTokens.canonicalName = tokens.canonicalName;
			getterTokens.actualName = tokens.actualName;
			getterTokens.keys = new String[tokens.keys.length - 1];
			System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);
			Object propValue = null;
			try {
				propValue = getPropertyValue(getterTokens);
			}
			catch (NotReadablePropertyException ex) {
				throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
						"Cannot access indexed value in property referenced " +
						"in indexed property path '" + propertyName + "'", ex);
			}
			// Set value for last key.
			String key = tokens.keys[tokens.keys.length - 1];
			if (propValue == null) {
				throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
						"Cannot access indexed value in property referenced " +
						"in indexed property path '" + propertyName + "': returned null");
			}
			else if (propValue.getClass().isArray()) {
				Class requiredType = propValue.getClass().getComponentType();
				int arrayIndex = Integer.parseInt(key);
				Object oldValue = null;
				try {				
					Object convertedValue = this.typeConverterDelegate.convertIfNecessary(
							propertyName, oldValue, newValue, requiredType);
					Array.set(propValue, Integer.parseInt(key), convertedValue);
				}
				catch (IllegalArgumentException ex) {
					PropertyChangeEvent pce =
							new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
					throw new TypeMismatchException(pce, requiredType, ex);
				}
				catch (IndexOutOfBoundsException ex) {
					throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
							"Invalid array index in property path '" + propertyName + "'", ex);
				}
			}
			else if (propValue instanceof List) {				
				PropertyDescriptor pd = getPropertyDescriptorInternal(tokens.actualName);
				Class requiredType = null;
				if (JdkVersion.getJavaVersion() >= JdkVersion.JDK_1_5) {
					requiredType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod());
				}
				List list = (List) propValue;
				int index = Integer.parseInt(key);
				Object oldValue = null;				
				try {
					Object convertedValue = this.typeConverterDelegate.convertIfNecessary(
							propertyName, oldValue, newValue, requiredType);
					if (index < list.size()) {
						list.set(index, convertedValue);
					}
					else if (index >= list.size()) {
						for (int i = list.size(); i < index; i++) {
							try {
								list.add(null);
							}
							catch (NullPointerException ex) {
								throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
										"Cannot set element with index " + index + " in List of size " +
										list.size() + ", accessed using property path '" + propertyName +
										"': List does not support filling up gaps with null elements");
							}
						}
						list.add(convertedValue);
					}
				}
				catch (IllegalArgumentException ex) {
					PropertyChangeEvent pce =
							new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
					throw new TypeMismatchException(pce, requiredType, ex);
				}
			}
			else if (propValue instanceof Map) {
				PropertyDescriptor pd = getPropertyDescriptorInternal(tokens.actualName);
				Class mapKeyType = null;
				Class mapValueType = null;
				if (JdkVersion.getJavaVersion() >= JdkVersion.JDK_1_5) {
					mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod());
					mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(pd.getReadMethod());
				}
				Map map = (Map) propValue;
				Object oldValue = null;				
				Object convertedMapKey = null;
				Object convertedMapValue = null;
				try {
					// IMPORTANT: Do not pass full property name in here - property editors
					// must not kick in for map keys but rather only for map values.
					convertedMapKey = this.typeConverterDelegate.convertIfNecessary(
							null, null, key, mapKeyType);
				}
				catch (IllegalArgumentException ex) {
					PropertyChangeEvent pce =
							new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
					throw new TypeMismatchException(pce, mapKeyType, ex);
				}
				try {
					// Pass full property name and old value in here, since we want full
					// conversion ability for map values.
					convertedMapValue = this.typeConverterDelegate.convertIfNecessary(
							propertyName, oldValue, newValue, mapValueType);
				}
				catch (IllegalArgumentException ex) {
					PropertyChangeEvent pce =
							new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
					throw new TypeMismatchException(pce, mapValueType, ex);
				}
				map.put(convertedMapKey, convertedMapValue);
			}
			else {
				throw new PropertyException(getRootClass(), this.nestedPath + propertyName,
						"Property referenced in indexed property path '" + propertyName +
						"' is neither an array nor a List nor a Map; returned value was [" + newValue + "]");
			}
		}

		else {			
			PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
			if (pd == null || pd.getWriteMethod() == null) {
				PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());
				throw new NotWritablePropertyException(
						getRootClass(), this.nestedPath + propertyName,
						matches.buildErrorMessage(), matches.getPossibleMatches());
			}

			Method readMethod = pd.getReadMethod();
			Method writeMethod = pd.getWriteMethod();
			Object oldValue = null;

			if (readMethod != null) {
				if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
					readMethod.setAccessible(true);
				}
				try {
					oldValue = readMethod.invoke(this.object, new Object[0]);
				}
				catch (Exception ex) {
					if (logger.isDebugEnabled()) {
						logger.debug("Could not read previous value of property '" + this.nestedPath + propertyName + "'", ex);
					}
				}
			}

			try {				
				boolean isProx=false;
				if(newValue!=null && newValue.getClass().getSimpleName().indexOf("$$Enhancer")>0)isProx=true;
				//增加对CGLIB增强的判断,凡是增强后的类型都不进行延迟加载
				Object convertedValue = isProx?newValue:this.typeConverterDelegate.convertIfNecessary(oldValue, newValue, pd);
				if (pd.getPropertyType().isPrimitive() && (convertedValue == null || "".equals(convertedValue))) {
					throw new IllegalArgumentException("Invalid value [" + newValue + "] for property '" +
							pd.getName() + "' of primitive type [" + pd.getPropertyType() + "]");
				}

				if (logger.isDebugEnabled()) {
					logger.debug("About to invoke write method [" + writeMethod + "] on object of class [" +
							this.object.getClass().getName() + "]");
				}
				if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
					writeMethod.setAccessible(true);
				}
				writeMethod.invoke(this.object, new Object[] {convertedValue});
				if (logger.isDebugEnabled()) {
					logger.debug("Invoked write method [" + writeMethod + "] with value of type [" +
							pd.getPropertyType().getName() + "]");
				}
			}
			catch (InvocationTargetException ex) {
				PropertyChangeEvent propertyChangeEvent =
						new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
				if (ex.getTargetException() instanceof ClassCastException) {
					throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());
				}
				else {
					throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());
				}
			}
			catch (IllegalArgumentException ex) {
				PropertyChangeEvent pce =
						new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
				throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
			}
			catch (IllegalAccessException ex) {
				PropertyChangeEvent pce =
						new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, newValue);
				throw new MethodInvocationException(pce, ex);
			}
		}
	}


	public String toString() {
		StringBuffer sb = new StringBuffer("BeanWrapperImpl: wrapping class [");
		sb.append(getWrappedClass().getName()).append("]");
		return sb.toString();
	}


	//---------------------------------------------------------------------
	// Inner class for internal use
	//---------------------------------------------------------------------

	private static class PropertyTokenHolder {

		private String canonicalName;

		private String actualName;

		private String[] keys;
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -