Mercurial > hg > Members > sugi > MessagePack-java
diff src/main/java/org/msgpack/template/builder/beans/IndexedPropertyDescriptor.java @ 0:cb825acd883a
first commit
author | sugi |
---|---|
date | Sat, 18 Oct 2014 15:06:15 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/msgpack/template/builder/beans/IndexedPropertyDescriptor.java Sat Oct 18 15:06:15 2014 +0900 @@ -0,0 +1,383 @@ +// MODIFIED FOR THE MSGPACK PROJECT +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You 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.msgpack.template.builder.beans; + +import java.lang.reflect.Method; + +import org.apache.harmony.beans.BeansUtils; +import org.apache.harmony.beans.internal.nls.Messages; + +public class IndexedPropertyDescriptor extends PropertyDescriptor { + + private Class<?> indexedPropertyType; + + private Method indexedGetter; + + private Method indexedSetter; + + /** + * Constructs a new instance of <code>IndexedPropertyDescriptor</code>. + * + * @param propertyName + * the specified indexed property's name. + * @param beanClass + * the bean class + * @param getterName + * the name of the array getter + * @param setterName + * the name of the array setter + * @param indexedGetterName + * the name of the indexed getter. + * @param indexedSetterName + * the name of the indexed setter. + * @throws IntrospectionException + */ + public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass, + String getterName, String setterName, String indexedGetterName, + String indexedSetterName) throws IntrospectionException { + super(propertyName, beanClass, getterName, setterName); + setIndexedByName(beanClass, indexedGetterName, indexedSetterName); + } + + private void setIndexedByName(Class<?> beanClass, String indexedGetterName, + String indexedSetterName) throws IntrospectionException { + + String theIndexedGetterName = indexedGetterName; + if (theIndexedGetterName == null) { + if (indexedSetterName != null) { + setIndexedWriteMethod(beanClass, indexedSetterName); + } + } else { + if (theIndexedGetterName.length() == 0) { + theIndexedGetterName = "get" + name; //$NON-NLS-1$ + } + setIndexedReadMethod(beanClass, theIndexedGetterName); + if (indexedSetterName != null) { + setIndexedWriteMethod(beanClass, indexedSetterName, + indexedPropertyType); + } + } + + if (!isCompatible()) { + // custom.beans.57=Property type is incompatible with the indexed property type + throw new IntrospectionException(Messages.getString("custom.beans.57")); //$NON-NLS-1$ + } + } + + private boolean isCompatible() { + Class<?> propertyType = getPropertyType(); + + if (propertyType == null) { + return true; + } + Class<?> componentTypeOfProperty = propertyType.getComponentType(); + if (componentTypeOfProperty == null) { + return false; + } + if (indexedPropertyType == null) { + return false; + } + + return componentTypeOfProperty.getName().equals( + indexedPropertyType.getName()); + } + + /** + * Constructs a new instance of <code>IndexedPropertyDescriptor</code>. + * + * @param propertyName + * the specified indexed property's name. + * @param getter + * the array getter + * @param setter + * the array setter + * @param indexedGetter + * the indexed getter + * @param indexedSetter + * the indexed setter + * @throws IntrospectionException + */ + public IndexedPropertyDescriptor(String propertyName, Method getter, + Method setter, Method indexedGetter, Method indexedSetter) + throws IntrospectionException { + super(propertyName, getter, setter); + if (indexedGetter != null) { + internalSetIndexedReadMethod(indexedGetter); + internalSetIndexedWriteMethod(indexedSetter, true); + } else { + internalSetIndexedWriteMethod(indexedSetter, true); + internalSetIndexedReadMethod(indexedGetter); + } + + if (!isCompatible()) { + // custom.beans.57=Property type is incompatible with the indexed property type + throw new IntrospectionException(Messages.getString("custom.beans.57")); //$NON-NLS-1$ + } + } + + /** + * Constructs a new instance of <code>IndexedPropertyDescriptor</code>. + * + * @param propertyName + * the specified indexed property's name. + * @param beanClass + * the bean class. + * @throws IntrospectionException + */ + public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass) + throws IntrospectionException { + super(propertyName, beanClass); + setIndexedByName(beanClass, "get" //$NON-NLS-1$ + .concat(initialUpperCase(propertyName)), "set" //$NON-NLS-1$ + .concat(initialUpperCase(propertyName))); + } + + /** + * Sets the indexed getter as the specified method. + * + * @param indexedGetter + * the specified indexed getter. + * @throws IntrospectionException + */ + public void setIndexedReadMethod(Method indexedGetter) + throws IntrospectionException { + this.internalSetIndexedReadMethod(indexedGetter); + } + + /** + * Sets the indexed setter as the specified method. + * + * @param indexedSetter + * the specified indexed setter. + * @throws IntrospectionException + */ + public void setIndexedWriteMethod(Method indexedSetter) + throws IntrospectionException { + this.internalSetIndexedWriteMethod(indexedSetter, false); + } + + /** + * Obtains the indexed setter. + * + * @return the indexed setter. + */ + public Method getIndexedWriteMethod() { + return indexedSetter; + } + + /** + * Obtains the indexed getter. + * + * @return the indexed getter. + */ + public Method getIndexedReadMethod() { + return indexedGetter; + } + + /** + * Determines if this <code>IndexedPropertyDescriptor</code> is equal to + * the specified object. Two <code>IndexedPropertyDescriptor</code> s are + * equal if the reader, indexed reader, writer, indexed writer, property + * types, indexed property type, property editor and flags are equal. + * + * @param obj + * @return true if this indexed property descriptor is equal to the + * specified object. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IndexedPropertyDescriptor)) { + return false; + } + + IndexedPropertyDescriptor other = (IndexedPropertyDescriptor) obj; + + return (super.equals(other) + && (indexedPropertyType == null ? other.indexedPropertyType == null + : indexedPropertyType.equals(other.indexedPropertyType)) + && (indexedGetter == null ? other.indexedGetter == null + : indexedGetter.equals(other.indexedGetter)) && (indexedSetter == null ? other.indexedSetter == null + : indexedSetter.equals(other.indexedSetter))); + } + + /** + * HashCode of the IndexedPropertyDescriptor + */ + @Override + public int hashCode() { + return super.hashCode() + BeansUtils.getHashCode(indexedPropertyType) + + BeansUtils.getHashCode(indexedGetter) + + BeansUtils.getHashCode(indexedSetter); + } + + /** + * Obtains the Class object of the indexed property type. + * + * @return the Class object of the indexed property type. + */ + public Class<?> getIndexedPropertyType() { + return indexedPropertyType; + } + + private void setIndexedReadMethod(Class<?> beanClass, String indexedGetterName) + throws IntrospectionException { + Method getter; + try { + getter = beanClass.getMethod(indexedGetterName, + new Class[] { Integer.TYPE }); + } catch (NoSuchMethodException exception) { + // custom.beans.58=No such indexed read method + throw new IntrospectionException(Messages.getString("custom.beans.58")); //$NON-NLS-1$ + } catch (SecurityException exception) { + // custom.beans.59=Security violation accessing indexed read method + throw new IntrospectionException(Messages.getString("custom.beans.59")); //$NON-NLS-1$ + } + internalSetIndexedReadMethod(getter); + } + + private void internalSetIndexedReadMethod(Method indexGetter) + throws IntrospectionException { + // Clearing the indexed read method. + if (indexGetter == null) { + if (indexedSetter == null) { + if (getPropertyType() != null) { + // custom.beans.5A=Indexed method is not compatible with non indexed method + throw new IntrospectionException(Messages + .getString("custom.beans.5A")); //$NON-NLS-1$ + } + indexedPropertyType = null; + } + this.indexedGetter = null; + return; + } + // Validate the indexed getter. + if ((indexGetter.getParameterTypes().length != 1) + || (indexGetter.getParameterTypes()[0] != Integer.TYPE)) { + // custom.beans.5B=Indexed read method must take a single int argument + throw new IntrospectionException(Messages.getString("custom.beans.5B")); //$NON-NLS-1$ + } + Class<?> indexedReadType = indexGetter.getReturnType(); + if (indexedReadType == Void.TYPE) { + // custom.beans.5B=Indexed read method must take a single int argument + throw new IntrospectionException(Messages.getString("custom.beans.5B")); //$NON-NLS-1$ + } else if (indexedSetter != null + && indexGetter.getReturnType() != indexedSetter + .getParameterTypes()[1]) { + // custom.beans.5A=Indexed read method is not compatible with indexed write method + throw new IntrospectionException(Messages.getString("custom.beans.5A")); //$NON-NLS-1$ + } + + // Set the indexed property type if not already set, confirm validity if + // it is. + if (this.indexedGetter == null) { + indexedPropertyType = indexedReadType; + } else { + if (indexedPropertyType != indexedReadType) { + // custom.beans.5A=Indexed read method is not compatible with indexed write method + throw new IntrospectionException(Messages.getString("custom.beans.5A")); //$NON-NLS-1$ + } + } + + // Set the indexed getter + this.indexedGetter = indexGetter; + } + + private void setIndexedWriteMethod(Class<?> beanClass, String indexedSetterName) + throws IntrospectionException { + Method setter = null; + try { + setter = beanClass.getMethod(indexedSetterName, new Class[] { + Integer.TYPE, getPropertyType().getComponentType() }); + } catch (SecurityException e) { + // custom.beans.5C=Security violation accessing indexed write method + throw new IntrospectionException(Messages.getString("custom.beans.5C")); //$NON-NLS-1$ + } catch (NoSuchMethodException e) { + // custom.beans.5D=No such indexed write method + throw new IntrospectionException(Messages.getString("custom.beans.5D")); //$NON-NLS-1$ + } + internalSetIndexedWriteMethod(setter, true); + } + + private void setIndexedWriteMethod(Class<?> beanClass, + String indexedSetterName, Class<?> argType) + throws IntrospectionException { + try { + Method setter = beanClass.getMethod(indexedSetterName, new Class[] { + Integer.TYPE, argType }); + internalSetIndexedWriteMethod(setter, true); + } catch (NoSuchMethodException exception) { + // custom.beans.5D=No such indexed write method + throw new IntrospectionException(Messages.getString("custom.beans.5D")); //$NON-NLS-1$ + } catch (SecurityException exception) { + // custom.beans.5C=Security violation accessing indexed write method + throw new IntrospectionException(Messages.getString("custom.beans.5C")); //$NON-NLS-1$ + } + } + + private void internalSetIndexedWriteMethod(Method indexSetter, + boolean initialize) throws IntrospectionException { + // Clearing the indexed write method. + if (indexSetter == null) { + if (indexedGetter == null) { + if (getPropertyType() != null) { + // custom.beans.5E=Indexed method is not compatible with non indexed method + throw new IntrospectionException(Messages + .getString("custom.beans.5E")); //$NON-NLS-1$ + } + indexedPropertyType = null; + } + this.indexedSetter = null; + return; + } + + // Validate the indexed write method. + Class<?>[] indexedSetterArgs = indexSetter.getParameterTypes(); + if (indexedSetterArgs.length != 2) { + // custom.beans.5F=Indexed write method must take two arguments + throw new IntrospectionException(Messages.getString("custom.beans.5F")); //$NON-NLS-1$ + } + if (indexedSetterArgs[0] != Integer.TYPE) { + // custom.beans.60=Indexed write method must take an int as its first argument + throw new IntrospectionException(Messages.getString("custom.beans.60")); //$NON-NLS-1$ + } + + // Set the indexed property type if not already set, confirm validity if + // it is. + Class<?> indexedWriteType = indexedSetterArgs[1]; + if (initialize && indexedGetter == null) { + indexedPropertyType = indexedWriteType; + } else { + if (indexedPropertyType != indexedWriteType) { + // custom.beans.61=Indexed write method is not compatible with indexed read method + throw new IntrospectionException(Messages.getString("custom.beans.61")); //$NON-NLS-1$ + } + } + + // Set the indexed write method. + this.indexedSetter = indexSetter; + } + + private static String initialUpperCase(String string) { + if (Character.isUpperCase(string.charAt(0))) { + return string; + } + + String initial = string.substring(0, 1).toUpperCase(); + return initial.concat(string.substring(1)); + } +}