List of usage examples for java.beans PropertyDescriptor getPropertyType
public synchronized Class<?> getPropertyType()
From source file:org.kuali.rice.krad.service.impl.DictionaryValidationServiceImpl.java
/** * iterates through the property descriptors looking for business objects or lists of business objects. calls * validate method/*from w ww . j a v a 2s.com*/ * for each bo found * * @param object * @param propertyDescriptors */ protected void validateBusinessObjectsFromDescriptors(Object object, PropertyDescriptor[] propertyDescriptors, int depth) { DataObjectWrapper<Object> wrapper = KradDataServiceLocator.getDataObjectService().wrap(object); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { // validate the properties that are descended from BusinessObject if (propertyDescriptor.getPropertyType() != null && PersistableBusinessObject.class.isAssignableFrom(propertyDescriptor.getPropertyType()) && wrapper.getPropertyValueNullSafe(propertyDescriptor.getName()) != null) { BusinessObject bo = (BusinessObject) wrapper.getPropertyValueNullSafe(propertyDescriptor.getName()); if (depth == 0) { GlobalVariables.getMessageMap().addToErrorPath(propertyDescriptor.getName()); validateBusinessObject(bo); GlobalVariables.getMessageMap().removeFromErrorPath(propertyDescriptor.getName()); } else { validateBusinessObjectsRecursively(bo, depth - 1); } } /* * if property is a List, then walk the list and do the validation on each contained object that is a descendent of * BusinessObject */ else if (propertyDescriptor.getPropertyType() != null && (List.class).isAssignableFrom(propertyDescriptor.getPropertyType()) && wrapper.getPropertyValueNullSafe(propertyDescriptor.getName()) != null) { List propertyList = (List) wrapper.getPropertyValueNullSafe(propertyDescriptor.getName()); for (int j = 0; j < propertyList.size(); j++) { if (propertyList.get(j) != null && propertyList.get(j) instanceof PersistableBusinessObject) { if (depth == 0) { GlobalVariables.getMessageMap() .addToErrorPath(StringUtils.chomp(propertyDescriptor.getName(), "s") + "[" + (new Integer(j)).toString() + "]"); validateBusinessObject((BusinessObject) propertyList.get(j)); GlobalVariables.getMessageMap() .removeFromErrorPath(StringUtils.chomp(propertyDescriptor.getName(), "s") + "[" + (new Integer(j)).toString() + "]"); } else { validateBusinessObjectsRecursively((BusinessObject) propertyList.get(j), depth - 1); } } } } } }
From source file:de.xwic.appkit.core.transport.xml.XmlBeanSerializer.java
/** * @param doc//from ww w . j a v a 2 s . c om * @param string * @param query * @throws IntrospectionException * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException */ public void serializeBean(Element elm, String elementName, Object bean) throws TransportException { Element root = elm.addElement(elementName); root.addAttribute("type", bean.getClass().getName()); try { BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { if (!"class".equals(pd.getName())) { Element pElm = root.addElement(pd.getName()); Method mRead = pd.getReadMethod(); if (mRead == null) { log.debug(String.format("No '%s' property on '%s'.", pd.getName(), bean.getClass())); continue; } Object value = mRead.invoke(bean, NO_ARGS); boolean addType = true; addType = value != null && !value.getClass().equals(pd.getPropertyType()) && !pd.getPropertyType().isPrimitive(); addValue(pElm, value, addType); } } } catch (Exception e) { throw new TransportException("Error serializing bean: " + e, e); } }
From source file:org.kuali.rice.krad.service.impl.KRADLegacyDataAdapterImpl.java
@Override public void setObjectPropertyDeep(Object bo, String propertyName, Class type, Object propertyValue) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { DataObjectWrapper<Object> dataObjectWrapper = dataObjectService.wrap(bo); // Base return cases to avoid null pointers & infinite loops if (KRADUtils.isNull(bo) || !PropertyUtils.isReadable(bo, propertyName) || (propertyValue != null//from w ww. j a va2 s .co m && propertyValue.equals(dataObjectWrapper.getPropertyValueNullSafe(propertyName))) || (type != null && !type.equals(KRADUtils.easyGetPropertyType(bo, propertyName)))) { return; } // Set the property in the BO KRADUtils.setObjectProperty(bo, propertyName, type, propertyValue); // Now drill down and check nested BOs and BO lists PropertyDescriptor[] propertyDescriptors = PropertyUtils.getPropertyDescriptors(bo.getClass()); for (int i = 0; i < propertyDescriptors.length; i++) { PropertyDescriptor propertyDescriptor = propertyDescriptors[i]; // Business Objects if (propertyDescriptor.getPropertyType() != null && (BusinessObject.class).isAssignableFrom(propertyDescriptor.getPropertyType()) && PropertyUtils.isReadable(bo, propertyDescriptor.getName())) { Object nestedBo = dataObjectWrapper.getPropertyValueNullSafe(propertyDescriptor.getName()); if (nestedBo instanceof BusinessObject) { setObjectPropertyDeep(nestedBo, propertyName, type, propertyValue); } } // Lists else if (propertyDescriptor.getPropertyType() != null && (List.class).isAssignableFrom(propertyDescriptor.getPropertyType()) && dataObjectWrapper.getPropertyValueNullSafe(propertyDescriptor.getName()) != null) { List propertyList = (List) dataObjectWrapper.getPropertyValueNullSafe(propertyDescriptor.getName()); for (Object listedBo : propertyList) { if (listedBo != null && listedBo instanceof BusinessObject) { setObjectPropertyDeep(listedBo, propertyName, type, propertyValue); } } // end for } } // end for }
From source file:net.solarnetwork.node.support.XmlServiceSupport.java
private void writeURLEncodedBeanProperties(BeanWrapper bean, Map<String, ?> attributes, Writer out) throws IOException { PropertyDescriptor[] props = bean.getPropertyDescriptors(); boolean propsWritten = false; if (attributes != null && attributes.containsKey(ATTR_NODE_ID)) { out.write("nodeId=" + attributes.get(ATTR_NODE_ID)); propsWritten = true;// w ww . j av a 2 s. c om } for (int i = 0; i < props.length; i++) { PropertyDescriptor prop = props[i]; if (prop.getReadMethod() == null) { continue; } String propName = prop.getName(); if ("class".equals(propName)) { continue; } Object propValue = null; if (attributes != null && attributes.containsKey(propName)) { propValue = attributes.get(propName); } else { PropertyEditor editor = bean.findCustomEditor(prop.getPropertyType(), prop.getName()); if (editor != null) { editor.setValue(bean.getPropertyValue(propName)); propValue = editor.getAsText(); } else { propValue = bean.getPropertyValue(propName); } } if (propValue == null) { continue; } if (propsWritten) { out.write("&"); } out.write(propName); out.write("="); out.write(URLEncoder.encode(propValue.toString(), "UTF-8")); propsWritten = true; } out.flush(); out.close(); }
From source file:org.kuali.rice.krad.service.impl.PersistenceStructureServiceOjbImpl.java
/** * @see org.kuali.rice.krad.service.PersistenceService#getForeignKeyFieldsPopulationState(org.kuali.rice.krad.bo.BusinessObject, * java.lang.String)/* www . j av a2 s. c om*/ */ @Override public ForeignKeyFieldsPopulationState getForeignKeyFieldsPopulationState(PersistableBusinessObject bo, String referenceName) { boolean allFieldsPopulated = true; boolean anyFieldsPopulated = false; List<String> unpopulatedFields = new ArrayList<String>(); // yelp if nulls were passed in if (bo == null) { throw new IllegalArgumentException("The Class passed in for the BusinessObject argument was null."); } if (StringUtils.isBlank(referenceName)) { throw new IllegalArgumentException( "The String passed in for the referenceName argument was null or empty."); } PropertyDescriptor propertyDescriptor = null; // make sure the attribute exists at all, throw exception if not try { propertyDescriptor = PropertyUtils.getPropertyDescriptor(bo, referenceName); } catch (Exception e) { throw new RuntimeException(e); } if (propertyDescriptor == null) { throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + referenceName + "' does not exist " + "on class: '" + bo.getClass().getName() + "'."); } // get the class of the attribute name Class referenceClass = propertyDescriptor.getPropertyType(); // make sure the class of the attribute descends from BusinessObject, // otherwise throw an exception if (!PersistableBusinessObject.class.isAssignableFrom(referenceClass)) { throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + referenceName + ") is of class: " + "'" + referenceClass.getName() + "' and is not a " + "descendent of BusinessObject. Only descendents of BusinessObject " + "can be used."); } // make sure the attribute designated is listed as a // reference-descriptor // on the clazz specified, otherwise throw an exception (OJB); ClassDescriptor classDescriptor = getClassDescriptor(bo.getClass()); // This block is a combination of legacy and jpa ObjectReferenceDescriptor referenceDescriptor = classDescriptor .getObjectReferenceDescriptorByName(referenceName); if (referenceDescriptor == null) { throw new ReferenceAttributeNotAnOjbReferenceException( "Attribute requested (" + referenceName + ") is not listed " + "in OJB as a reference-descriptor for class: '" + bo.getClass().getName() + "'"); } // get the list of the foreign-keys for this reference-descriptor Vector fkFieldsLegacy = referenceDescriptor.getForeignKeyFields(); Iterator fkIteratorLegacy = fkFieldsLegacy.iterator(); // walk through the list of the foreign keys, get their types while (fkIteratorLegacy.hasNext()) { // get the field name of the fk & pk field String fkFieldName = (String) fkIteratorLegacy.next(); // get the value for the fk field Object fkFieldValue = null; try { fkFieldValue = PropertyUtils.getSimpleProperty(bo, fkFieldName); } // abort if the value is not retrievable catch (Exception e) { throw new RuntimeException(e); } // test the value if (fkFieldValue == null) { allFieldsPopulated = false; unpopulatedFields.add(fkFieldName); } else if (fkFieldValue instanceof String) { if (StringUtils.isBlank((String) fkFieldValue)) { allFieldsPopulated = false; unpopulatedFields.add(fkFieldName); } else { anyFieldsPopulated = true; } } else { anyFieldsPopulated = true; } } // sanity check. if the flag for all fields populated is set, then // there should be nothing in the unpopulatedFields list if (allFieldsPopulated) { if (!unpopulatedFields.isEmpty()) { throw new RuntimeException("The flag is set that indicates all fields are populated, but there " + "are fields present in the unpopulatedFields list. This should never happen, and indicates " + "that the logic in this method is broken."); } } return new ForeignKeyFieldsPopulationState(allFieldsPopulated, anyFieldsPopulated, unpopulatedFields); }
From source file:org.enerj.apache.commons.beanutils.BeanUtilsBean.java
/** * <p>Copy the specified property value to the specified destination bean, * performing any type conversion that is required. If the specified * bean does not have a property of the specified name, or the property * is read only on the destination bean, return without * doing anything. If you have custom destination property types, register * {@link Converter}s for them by calling the <code>register()</code> * method of {@link ConvertUtils}.</p> * * <p><strong>IMPLEMENTATION RESTRICTIONS</strong>:</p> * <ul>/* w w w . j ava 2 s . c om*/ * <li>Does not support destination properties that are indexed, * but only an indexed setter (as opposed to an array setter) * is available.</li> * <li>Does not support destination properties that are mapped, * but only a keyed setter (as opposed to a Map setter) * is available.</li> * <li>The desired property type of a mapped setter cannot be * determined (since Maps support any data type), so no conversion * will be performed.</li> * </ul> * * @param bean Bean on which setting is to be performed * @param name Property name (can be nested/indexed/mapped/combo) * @param value Value to be set * * @exception IllegalAccessException if the caller does not have * access to the property accessor method * @exception InvocationTargetException if the property accessor method * throws an exception */ public void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException { // Trace logging (if enabled) if (log.isTraceEnabled()) { StringBuffer sb = new StringBuffer(" copyProperty("); sb.append(bean); sb.append(", "); sb.append(name); sb.append(", "); if (value == null) { sb.append("<NULL>"); } else if (value instanceof String) { sb.append((String) value); } else if (value instanceof String[]) { String values[] = (String[]) value; sb.append('['); for (int i = 0; i < values.length; i++) { if (i > 0) { sb.append(','); } sb.append(values[i]); } sb.append(']'); } else { sb.append(value.toString()); } sb.append(')'); log.trace(sb.toString()); } // Resolve any nested expression to get the actual target bean Object target = bean; int delim = name.lastIndexOf(PropertyUtils.NESTED_DELIM); if (delim >= 0) { try { target = getPropertyUtils().getProperty(bean, name.substring(0, delim)); } catch (NoSuchMethodException e) { return; // Skip this property setter } name = name.substring(delim + 1); if (log.isTraceEnabled()) { log.trace(" Target bean = " + target); log.trace(" Target name = " + name); } } // Declare local variables we will require String propName = null; // Simple name of target property Class type = null; // Java type of target property int index = -1; // Indexed subscript value (if any) String key = null; // Mapped key value (if any) // Calculate the target property name, index, and key values propName = name; int i = propName.indexOf(PropertyUtils.INDEXED_DELIM); if (i >= 0) { int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2); try { index = Integer.parseInt(propName.substring(i + 1, k)); } catch (NumberFormatException e) { ; } propName = propName.substring(0, i); } int j = propName.indexOf(PropertyUtils.MAPPED_DELIM); if (j >= 0) { int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2); try { key = propName.substring(j + 1, k); } catch (IndexOutOfBoundsException e) { ; } propName = propName.substring(0, j); } // Calculate the target property type if (target instanceof DynaBean) { DynaClass dynaClass = ((DynaBean) target).getDynaClass(); DynaProperty dynaProperty = dynaClass.getDynaProperty(propName); if (dynaProperty == null) { return; // Skip this property setter } type = dynaProperty.getType(); } else { PropertyDescriptor descriptor = null; try { descriptor = getPropertyUtils().getPropertyDescriptor(target, name); if (descriptor == null) { return; // Skip this property setter } } catch (NoSuchMethodException e) { return; // Skip this property setter } type = descriptor.getPropertyType(); if (type == null) { // Most likely an indexed setter on a POJB only if (log.isTraceEnabled()) { log.trace(" target type for property '" + propName + "' is null, so skipping ths setter"); } return; } } if (log.isTraceEnabled()) { log.trace(" target propName=" + propName + ", type=" + type + ", index=" + index + ", key=" + key); } // Convert the specified value to the required type and store it if (index >= 0) { // Destination must be indexed Converter converter = getConvertUtils().lookup(type.getComponentType()); if (converter != null) { log.trace(" USING CONVERTER " + converter); value = converter.convert(type, value); } try { getPropertyUtils().setIndexedProperty(target, propName, index, value); } catch (NoSuchMethodException e) { throw new InvocationTargetException(e, "Cannot set " + propName); } } else if (key != null) { // Destination must be mapped // Maps do not know what the preferred data type is, // so perform no conversions at all // FIXME - should we create or support a TypedMap? try { getPropertyUtils().setMappedProperty(target, propName, key, value); } catch (NoSuchMethodException e) { throw new InvocationTargetException(e, "Cannot set " + propName); } } else { // Destination must be simple Converter converter = getConvertUtils().lookup(type); if (converter != null) { log.trace(" USING CONVERTER " + converter); value = converter.convert(type, value); } try { getPropertyUtils().setSimpleProperty(target, propName, value); } catch (NoSuchMethodException e) { throw new InvocationTargetException(e, "Cannot set " + propName); } } }
From source file:org.evergreen.web.utils.beanutils.BeanUtilsBean.java
/** * <p>Copy the specified property value to the specified destination bean, * performing any type conversion that is required. If the specified * bean does not have a property of the specified name, or the property * is read only on the destination bean, return without * doing anything. If you have custom destination property types, register * {@link Converter}s for them by calling the <code>register()</code> * method of {@link ConvertUtils}.</p> * * <p><strong>IMPLEMENTATION RESTRICTIONS</strong>:</p> * <ul>/*from ww w .jav a 2 s .c o m*/ * <li>Does not support destination properties that are indexed, * but only an indexed setter (as opposed to an array setter) * is available.</li> * <li>Does not support destination properties that are mapped, * but only a keyed setter (as opposed to a Map setter) * is available.</li> * <li>The desired property type of a mapped setter cannot be * determined (since Maps support any data type), so no conversion * will be performed.</li> * </ul> * * @param bean Bean on which setting is to be performed * @param name Property name (can be nested/indexed/mapped/combo) * @param value Value to be set * * @exception IllegalAccessException if the caller does not have * access to the property accessor method * @exception InvocationTargetException if the property accessor method * throws an exception */ public void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException { // Trace logging (if enabled) if (log.isTraceEnabled()) { StringBuffer sb = new StringBuffer(" copyProperty("); sb.append(bean); sb.append(", "); sb.append(name); sb.append(", "); if (value == null) { sb.append("<NULL>"); } else if (value instanceof String) { sb.append((String) value); } else if (value instanceof String[]) { String[] values = (String[]) value; sb.append('['); for (int i = 0; i < values.length; i++) { if (i > 0) { sb.append(','); } sb.append(values[i]); } sb.append(']'); } else { sb.append(value.toString()); } sb.append(')'); log.trace(sb.toString()); } // Resolve any nested expression to get the actual target bean Object target = bean; Resolver resolver = getPropertyUtils().getResolver(); while (resolver.hasNested(name)) { try { target = getPropertyUtils().getProperty(target, resolver.next(name)); name = resolver.remove(name); } catch (NoSuchMethodException e) { return; // Skip this property setter } } if (log.isTraceEnabled()) { log.trace(" Target bean = " + target); log.trace(" Target name = " + name); } // Declare local variables we will require String propName = resolver.getProperty(name); // Simple name of target property Class type = null; // Java type of target property int index = resolver.getIndex(name); // Indexed subscript value (if any) String key = resolver.getKey(name); // Mapped key value (if any) // Calculate the target property type if (target instanceof DynaBean) { DynaClass dynaClass = ((DynaBean) target).getDynaClass(); DynaProperty dynaProperty = dynaClass.getDynaProperty(propName); if (dynaProperty == null) { return; // Skip this property setter } type = dynaProperty.getType(); } else { PropertyDescriptor descriptor = null; try { descriptor = getPropertyUtils().getPropertyDescriptor(target, name); if (descriptor == null) { return; // Skip this property setter } } catch (NoSuchMethodException e) { return; // Skip this property setter } type = descriptor.getPropertyType(); if (type == null) { // Most likely an indexed setter on a POJB only if (log.isTraceEnabled()) { log.trace(" target type for property '" + propName + "' is null, so skipping ths setter"); } return; } } if (log.isTraceEnabled()) { log.trace(" target propName=" + propName + ", type=" + type + ", index=" + index + ", key=" + key); } // Convert the specified value to the required type and store it if (index >= 0) { // Destination must be indexed value = convert(value, type.getComponentType()); try { getPropertyUtils().setIndexedProperty(target, propName, index, value); } catch (NoSuchMethodException e) { throw new InvocationTargetException(e, "Cannot set " + propName); } } else if (key != null) { // Destination must be mapped // Maps do not know what the preferred data type is, // so perform no conversions at all // FIXME - should we create or support a TypedMap? try { getPropertyUtils().setMappedProperty(target, propName, key, value); } catch (NoSuchMethodException e) { throw new InvocationTargetException(e, "Cannot set " + propName); } } else { // Destination must be simple value = convert(value, type); try { getPropertyUtils().setSimpleProperty(target, propName, value); } catch (NoSuchMethodException e) { throw new InvocationTargetException(e, "Cannot set " + propName); } } }
From source file:com.artistech.protobuf.TuioProtoConverter.java
@Override public Object convertFromProtobuf(final GeneratedMessage obj) { Object target;/*from w w w .ja v a 2s. c o m*/ if (TuioProtos.Blob.class.isAssignableFrom(obj.getClass())) { target = new TUIO.TuioBlob(); } else if (TuioProtos.Time.class.isAssignableFrom(obj.getClass())) { target = new TUIO.TuioTime(); } else if (TuioProtos.Cursor.class.isAssignableFrom(obj.getClass())) { target = new TUIO.TuioCursor(); } else if (TuioProtos.Object.class.isAssignableFrom(obj.getClass())) { target = new TUIO.TuioObject(); } else if (TuioProtos.Point.class.isAssignableFrom(obj.getClass())) { target = new TUIO.TuioPoint(); } else { return null; } try { PropertyDescriptor[] targetProps = Introspector.getBeanInfo(target.getClass()).getPropertyDescriptors(); BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); PropertyDescriptor[] messageProps = beanInfo.getPropertyDescriptors(); Method[] methods = obj.getClass().getMethods(); for (PropertyDescriptor targetProp : targetProps) { for (PropertyDescriptor messageProp : messageProps) { if (targetProp.getName().equals(messageProp.getName())) { Method writeMethod = targetProp.getWriteMethod(); Method readMethod = null; for (Method m : methods) { if (writeMethod != null && m.getName().equals(writeMethod.getName().replaceFirst("set", "get"))) { readMethod = m; break; } } try { if (writeMethod != null && readMethod != null && targetProp.getReadMethod() != null) { boolean primitiveOrWrapper = ClassUtils .isPrimitiveOrWrapper(targetProp.getReadMethod().getReturnType()); if (readMethod.getParameterTypes().length > 0) { if (DeepCopy) { if (!Modifier.isAbstract(targetProp.getPropertyType().getModifiers())) { //basically, ArrayList Object newInstance = targetProp.getPropertyType().newInstance(); Method addMethod = newInstance.getClass().getMethod("add", Object.class); Method m = obj.getClass().getMethod(readMethod.getName() + "Count"); int size = (int) m.invoke(obj); for (int ii = 0; ii < size; ii++) { Object o = readMethod.invoke(obj, ii); addMethod.invoke(newInstance, o); } writeMethod.invoke(target, newInstance); } else if (Collection.class .isAssignableFrom(targetProp.getPropertyType())) { //do something if it is a collection or iterable... } } } else if (primitiveOrWrapper) { writeMethod.invoke(target, messageProp.getReadMethod().invoke(obj)); } else { if (GeneratedMessage.class .isAssignableFrom(messageProp.getReadMethod().getReturnType())) { GeneratedMessage invoke = (GeneratedMessage) messageProp.getReadMethod() .invoke(obj); Object val = null; for (ProtoConverter converter : services) { if (converter.supportsConversion(invoke)) { val = convertFromProtobuf(invoke); break; } } if (val != null) { writeMethod.invoke(target, val); } } // System.out.println("Prop1 Name!: " + targetProp.getName()); } } } catch (NullPointerException ex) { //Logger.getLogger(ZeroMqMouse.class.getName()).log(Level.SEVERE, null, ex); } catch (InstantiationException | NoSuchMethodException | IllegalArgumentException | SecurityException | IllegalAccessException | InvocationTargetException ex) { logger.error(ex); } break; } } } } catch (java.beans.IntrospectionException ex) { logger.fatal(ex); } return target; }
From source file:com.unboundid.scim2.common.utils.SchemaUtils.java
/** * Gets SCIM schema attributes for a class. * * @param classesProcessed a stack containing the classes processed prior * to this class. This is used for cycle detection. * @param cls the class to get the attributes for. * @return a collection of SCIM schema attributes for the class. * @throws IntrospectionException thrown if an error occurs during * Introspection.//from w w w . java2s.c o m */ private static Collection<AttributeDefinition> getAttributes(final Stack<String> classesProcessed, final Class<?> cls) throws IntrospectionException { String className = cls.getCanonicalName(); if (!cls.isAssignableFrom(AttributeDefinition.class) && classesProcessed.contains(className)) { throw new RuntimeException("Cycles detected in Schema"); } Collection<PropertyDescriptor> propertyDescriptors = getPropertyDescriptors(cls); Collection<AttributeDefinition> attributes = new ArrayList<AttributeDefinition>(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { if (propertyDescriptor.getName().equals("subAttributes") && cls.isAssignableFrom(AttributeDefinition.class) && classesProcessed.contains(className)) { // Skip second nesting of subAttributes the second time around // since there is no subAttributes of subAttributes in SCIM. continue; } AttributeDefinition.Builder attributeBuilder = new AttributeDefinition.Builder(); Field field = findField(cls, propertyDescriptor.getName()); if (field == null) { continue; } Attribute schemaProperty = null; JsonProperty jsonProperty = null; if (field.isAnnotationPresent(Attribute.class)) { schemaProperty = field.getAnnotation(Attribute.class); } if (field.isAnnotationPresent(JsonProperty.class)) { jsonProperty = field.getAnnotation(JsonProperty.class); } // Only generate schema for annotated fields. if (schemaProperty == null) { continue; } addName(attributeBuilder, propertyDescriptor, jsonProperty); addDescription(attributeBuilder, schemaProperty); addCaseExact(attributeBuilder, schemaProperty); addRequired(attributeBuilder, schemaProperty); addReturned(attributeBuilder, schemaProperty); addUniqueness(attributeBuilder, schemaProperty); addReferenceTypes(attributeBuilder, schemaProperty); addMutability(attributeBuilder, schemaProperty); addMultiValued(attributeBuilder, propertyDescriptor, schemaProperty); addCanonicalValues(attributeBuilder, schemaProperty); Class propertyCls = propertyDescriptor.getPropertyType(); // if this is a multivalued attribute the real sub attribute class is the // the one specified in the annotation, not the list, set, array, etc. if ((schemaProperty.multiValueClass() != NullType.class)) { propertyCls = schemaProperty.multiValueClass(); } AttributeDefinition.Type type = getAttributeType(propertyCls); attributeBuilder.setType(type); if (type == AttributeDefinition.Type.COMPLEX) { // Add this class to the list to allow cycle detection classesProcessed.push(cls.getCanonicalName()); Collection<AttributeDefinition> subAttributes = getAttributes(classesProcessed, propertyCls); attributeBuilder .addSubAttributes(subAttributes.toArray(new AttributeDefinition[subAttributes.size()])); classesProcessed.pop(); } attributes.add(attributeBuilder.build()); } return attributes; }