private static PropertyDescriptorComposite getCompositeProperties(
      EventType underlyingEventType, MapEventType underlyingMapType) {
    List<String> propertyNames = new ArrayList<String>();
    propertyNames.addAll(Arrays.asList(underlyingEventType.getPropertyNames()));
    propertyNames.addAll(Arrays.asList(underlyingMapType.getPropertyNames()));
    String[] propertyNamesArr = propertyNames.toArray(new String[propertyNames.size()]);

    List<EventPropertyDescriptor> propertyDesc = new ArrayList<EventPropertyDescriptor>();
    HashMap<String, EventPropertyDescriptor> propertyDescriptorMap =
        new HashMap<String, EventPropertyDescriptor>();
    for (EventPropertyDescriptor eventProperty : underlyingEventType.getPropertyDescriptors()) {
      propertyDesc.add(eventProperty);
      propertyDescriptorMap.put(eventProperty.getPropertyName(), eventProperty);
    }
    for (EventPropertyDescriptor mapProperty : underlyingMapType.getPropertyDescriptors()) {
      propertyDesc.add(mapProperty);
      propertyDescriptorMap.put(mapProperty.getPropertyName(), mapProperty);
    }
    EventPropertyDescriptor[] propertyDescArr =
        propertyDesc.toArray(new EventPropertyDescriptor[propertyDesc.size()]);
    return new PropertyDescriptorComposite(
        propertyDescriptorMap, propertyNamesArr, propertyDescArr);
  }
  private void initializeWriters() {
    List<EventPropertyDescriptor> writables = new ArrayList<EventPropertyDescriptor>();
    Map<String, Pair<EventPropertyDescriptor, EventPropertyWriter>> writerMap =
        new HashMap<String, Pair<EventPropertyDescriptor, EventPropertyWriter>>();
    writables.addAll(Arrays.asList(underlyingMapType.getWriteableProperties()));

    for (EventPropertyDescriptor writableMapProp : underlyingMapType.getWriteableProperties()) {
      final String propertyName = writableMapProp.getPropertyName();
      writables.add(writableMapProp);
      EventPropertyWriter writer =
          new EventPropertyWriter() {
            public void write(Object value, EventBean target) {
              DecoratingEventBean decorated = (DecoratingEventBean) target;
              decorated.getDecoratingProperties().put(propertyName, value);
            }
          };
      writerMap.put(
          propertyName,
          new Pair<EventPropertyDescriptor, EventPropertyWriter>(writableMapProp, writer));
    }

    if (underlyingEventType instanceof EventTypeSPI) {
      EventTypeSPI spi = (EventTypeSPI) underlyingEventType;
      for (EventPropertyDescriptor writableUndProp : spi.getWriteableProperties()) {
        final String propertyName = writableUndProp.getPropertyName();
        final EventPropertyWriter innerWriter = spi.getWriter(propertyName);
        if (innerWriter == null) {
          continue;
        }

        writables.add(writableUndProp);
        EventPropertyWriter writer =
            new EventPropertyWriter() {
              public void write(Object value, EventBean target) {
                DecoratingEventBean decorated = (DecoratingEventBean) target;
                innerWriter.write(value, decorated.getUnderlyingEvent());
              }
            };
        writerMap.put(
            propertyName,
            new Pair<EventPropertyDescriptor, EventPropertyWriter>(writableUndProp, writer));
      }
    }

    writers = writerMap;
    writableProperties = writables.toArray(new EventPropertyDescriptor[writables.size()]);
  }