public BaseCtoConverter getAdornedTargetCtoConverter(
     PersistencePerspective persistencePerspective,
     CriteriaTransferObject cto,
     Map<String, FieldMetadata> mergedProperties,
     AdornedTargetList adornedTargetList)
     throws ClassNotFoundException {
   BaseCtoConverter ctoConverter =
       getCtoConverter(
           persistencePerspective,
           cto,
           adornedTargetList.getAdornedTargetEntityClassname(),
           mergedProperties);
   ctoConverter.addLongEQMapping(
       adornedTargetList.getAdornedTargetEntityClassname(),
       adornedTargetList.getCollectionFieldName(),
       AssociationPath.ROOT,
       adornedTargetList.getLinkedObjectPath() + "." + adornedTargetList.getLinkedIdProperty());
   ctoConverter.addLongEQMapping(
       adornedTargetList.getAdornedTargetEntityClassname(),
       adornedTargetList.getCollectionFieldName() + "Target",
       AssociationPath.ROOT,
       adornedTargetList.getTargetObjectPath() + "." + adornedTargetList.getTargetIdProperty());
   return ctoConverter;
 }
 @Override
 public int getTotalRecords(
     PersistencePackage persistencePackage,
     CriteriaTransferObject cto,
     BaseCtoConverter ctoConverter)
     throws ClassNotFoundException {
   AdornedTargetList adornedTargetList =
       (AdornedTargetList)
           persistencePackage
               .getPersistencePerspective()
               .getPersistencePerspectiveItems()
               .get(PersistencePerspectiveItemType.ADORNEDTARGETLIST);
   PersistentEntityCriteria countCriteria =
       ctoConverter.convert(
           new CriteriaTransferObjectCountWrapper(cto).wrap(),
           adornedTargetList.getAdornedTargetEntityClassname());
   Class<?>[] entities =
       persistenceManager
           .getDynamicEntityDao()
           .getAllPolymorphicEntitiesFromCeiling(
               Class.forName(adornedTargetList.getAdornedTargetEntityClassname()));
   boolean isArchivable = false;
   for (Class<?> entity : entities) {
     if (Status.class.isAssignableFrom(entity)) {
       isArchivable = true;
       break;
     }
   }
   if (isArchivable && !persistencePackage.getPersistencePerspective().getShowArchivedFields()) {
     SimpleFilterCriterionProvider criterionProvider =
         new SimpleFilterCriterionProvider(
             SimpleFilterCriterionProvider.FilterDataStrategy.NONE, 0) {
           public Criterion getCriterion(
               String targetPropertyName, Object[] filterObjectValues, Object[] directValues) {
             return Restrictions.or(
                 Restrictions.eq(targetPropertyName, 'N'),
                 Restrictions.isNull(targetPropertyName));
           }
         };
     FilterCriterion filterCriterion =
         new FilterCriterion(AssociationPath.ROOT, "archiveStatus.archived", criterionProvider);
     ((NestedPropertyCriteria) countCriteria).add(filterCriterion);
   }
   return persistenceManager
       .getDynamicEntityDao()
       .count(countCriteria, Class.forName(adornedTargetList.getAdornedTargetEntityClassname()));
 }
    public AdornedTargetRetrieval invoke()
        throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
            InvocationTargetException, FieldNotAvailableException, NoSuchFieldException {
      CriteriaTransferObject cto = new CriteriaTransferObject();
      FilterAndSortCriteria filterCriteria = cto.get(adornedTargetList.getCollectionFieldName());
      filterCriteria.setFilterValue(
          entity
              .findProperty(
                  adornedTargetList.getLinkedObjectPath()
                      + "."
                      + adornedTargetList.getLinkedIdProperty())
              .getValue());
      if (adornedTargetList.getSortField() != null) {
        FilterAndSortCriteria sortCriteria = cto.get(adornedTargetList.getSortField());
        sortCriteria.setSortAscending(adornedTargetList.getSortAscending());
      }

      Class<?>[] entities2 =
          persistenceManager.getPolymorphicEntities(
              adornedTargetList.getAdornedTargetEntityClassname());
      mergedProperties =
          persistenceManager
              .getDynamicEntityDao()
              .getMergedProperties(
                  adornedTargetList.getAdornedTargetEntityClassname(),
                  entities2,
                  null,
                  new String[] {},
                  new ForeignKey[] {},
                  MergedPropertyType.ADORNEDTARGETLIST,
                  persistencePerspective.getPopulateToOneFields(),
                  persistencePerspective.getIncludeFields(),
                  persistencePerspective.getExcludeFields(),
                  persistencePerspective.getConfigurationKey(),
                  "");
      BaseCtoConverter ctoConverter =
          getAdornedTargetCtoConverter(
              persistencePerspective, cto, mergedProperties, adornedTargetList);
      PersistentEntityCriteria queryCriteria =
          ctoConverter.convert(cto, adornedTargetList.getAdornedTargetEntityClassname());
      records =
          persistenceManager
              .getDynamicEntityDao()
              .query(
                  queryCriteria,
                  Class.forName(adornedTargetList.getAdornedTargetEntityClassname()));

      index = 0;
      Long myEntityId =
          Long.valueOf(
              entity
                  .findProperty(
                      adornedTargetList.getTargetObjectPath()
                          + "."
                          + adornedTargetList.getTargetIdProperty())
                  .getValue());
      FieldManager fieldManager = getFieldManager();
      for (Serializable record : records) {
        Long targetId =
            (Long)
                fieldManager.getFieldValue(
                    record,
                    adornedTargetList.getTargetObjectPath()
                        + "."
                        + adornedTargetList.getTargetIdProperty());
        if (myEntityId.equals(targetId)) {
          break;
        }
        index++;
      }
      return this;
    }
  @Override
  public DynamicResultSet fetch(PersistencePackage persistencePackage, CriteriaTransferObject cto)
      throws ServiceException {
    PersistencePerspective persistencePerspective = persistencePackage.getPersistencePerspective();
    String ceilingEntityFullyQualifiedClassname =
        persistencePackage.getCeilingEntityFullyQualifiedClassname();
    AdornedTargetList adornedTargetList =
        (AdornedTargetList)
            persistencePerspective
                .getPersistencePerspectiveItems()
                .get(PersistencePerspectiveItemType.ADORNEDTARGETLIST);
    Entity[] payload;
    int totalRecords;
    try {
      Class<?>[] entities =
          persistenceManager.getPolymorphicEntities(ceilingEntityFullyQualifiedClassname);
      Map<String, FieldMetadata> mergedPropertiesTarget =
          persistenceManager
              .getDynamicEntityDao()
              .getMergedProperties(
                  ceilingEntityFullyQualifiedClassname,
                  entities,
                  null,
                  persistencePerspective.getAdditionalNonPersistentProperties(),
                  persistencePerspective.getAdditionalForeignKeys(),
                  MergedPropertyType.PRIMARY,
                  persistencePerspective.getPopulateToOneFields(),
                  persistencePerspective.getIncludeFields(),
                  persistencePerspective.getExcludeFields(),
                  persistencePerspective.getConfigurationKey(),
                  "");
      Class<?>[] entities2 =
          persistenceManager.getPolymorphicEntities(
              adornedTargetList.getAdornedTargetEntityClassname());
      Map<String, FieldMetadata> mergedProperties =
          persistenceManager
              .getDynamicEntityDao()
              .getMergedProperties(
                  adornedTargetList.getAdornedTargetEntityClassname(),
                  entities2,
                  null,
                  new String[] {},
                  new ForeignKey[] {},
                  MergedPropertyType.ADORNEDTARGETLIST,
                  false,
                  new String[] {},
                  new String[] {},
                  null,
                  "");
      BaseCtoConverter ctoConverter =
          getAdornedTargetCtoConverter(
              persistencePerspective, cto, mergedProperties, adornedTargetList);
      PersistentEntityCriteria queryCriteria =
          ctoConverter.convert(cto, adornedTargetList.getAdornedTargetEntityClassname());
      List<Serializable> records =
          persistenceManager
              .getDynamicEntityDao()
              .query(
                  queryCriteria,
                  Class.forName(adornedTargetList.getAdornedTargetEntityClassname()));
      payload =
          getRecords(
              mergedPropertiesTarget,
              records,
              mergedProperties,
              adornedTargetList.getTargetObjectPath());
      totalRecords = getTotalRecords(persistencePackage, cto, ctoConverter);
    } catch (Exception e) {
      LOG.error(
          "Problem fetching results for " + adornedTargetList.getAdornedTargetEntityClassname(), e);
      throw new ServiceException(
          "Unable to fetch results for " + adornedTargetList.getAdornedTargetEntityClassname(), e);
    }

    DynamicResultSet results = new DynamicResultSet(null, payload, totalRecords);

    return results;
  }
  @Override
  public void remove(PersistencePackage persistencePackage) throws ServiceException {
    String[] customCriteria = persistencePackage.getCustomCriteria();
    if (customCriteria != null && customCriteria.length > 0) {
      LOG.warn(
          "custom persistence handlers and custom criteria not supported for remove types other than BASIC");
    }
    PersistencePerspective persistencePerspective = persistencePackage.getPersistencePerspective();
    Entity entity = persistencePackage.getEntity();
    try {
      AdornedTargetList adornedTargetList =
          (AdornedTargetList)
              persistencePerspective
                  .getPersistencePerspectiveItems()
                  .get(PersistencePerspectiveItemType.ADORNEDTARGETLIST);
      Class<?>[] entities =
          persistenceManager.getPolymorphicEntities(
              adornedTargetList.getAdornedTargetEntityClassname());
      Map<String, FieldMetadata> mergedProperties =
          persistenceManager
              .getDynamicEntityDao()
              .getMergedProperties(
                  adornedTargetList.getAdornedTargetEntityClassname(),
                  entities,
                  null,
                  new String[] {},
                  new ForeignKey[] {},
                  MergedPropertyType.ADORNEDTARGETLIST,
                  false,
                  new String[] {},
                  new String[] {},
                  null,
                  "");
      CriteriaTransferObject ctoInserted = new CriteriaTransferObject();
      FilterAndSortCriteria filterCriteriaInsertedLinked =
          ctoInserted.get(adornedTargetList.getCollectionFieldName());
      filterCriteriaInsertedLinked.setFilterValue(
          entity
              .findProperty(
                  adornedTargetList.getLinkedObjectPath()
                      + "."
                      + adornedTargetList.getLinkedIdProperty())
              .getValue());
      FilterAndSortCriteria filterCriteriaInsertedTarget =
          ctoInserted.get(adornedTargetList.getCollectionFieldName() + "Target");
      filterCriteriaInsertedTarget.setFilterValue(
          entity
              .findProperty(
                  adornedTargetList.getTargetObjectPath()
                      + "."
                      + adornedTargetList.getTargetIdProperty())
              .getValue());
      BaseCtoConverter ctoConverterInserted =
          getAdornedTargetCtoConverter(
              persistencePerspective, ctoInserted, mergedProperties, adornedTargetList);
      PersistentEntityCriteria queryCriteriaInserted =
          ctoConverterInserted.convert(
              ctoInserted, adornedTargetList.getAdornedTargetEntityClassname());
      List<Serializable> recordsInserted =
          persistenceManager
              .getDynamicEntityDao()
              .query(
                  queryCriteriaInserted,
                  Class.forName(adornedTargetList.getAdornedTargetEntityClassname()));

      persistenceManager.getDynamicEntityDao().remove(recordsInserted.get(0));
    } catch (Exception e) {
      LOG.error("Problem removing entity", e);
      throw new ServiceException("Problem removing entity : " + e.getMessage(), e);
    }
  }
  @Override
  public Entity add(PersistencePackage persistencePackage) throws ServiceException {
    String[] customCriteria = persistencePackage.getCustomCriteria();
    if (customCriteria != null && customCriteria.length > 0) {
      LOG.warn(
          "custom persistence handlers and custom criteria not supported for add types other than BASIC");
    }
    PersistencePerspective persistencePerspective = persistencePackage.getPersistencePerspective();
    String ceilingEntityFullyQualifiedClassname =
        persistencePackage.getCeilingEntityFullyQualifiedClassname();
    Entity entity = persistencePackage.getEntity();
    AdornedTargetList adornedTargetList =
        (AdornedTargetList)
            persistencePerspective
                .getPersistencePerspectiveItems()
                .get(PersistencePerspectiveItemType.ADORNEDTARGETLIST);
    Entity payload;
    try {
      Class<?>[] entities =
          persistenceManager.getPolymorphicEntities(ceilingEntityFullyQualifiedClassname);
      Map<String, FieldMetadata> mergedPropertiesTarget =
          persistenceManager
              .getDynamicEntityDao()
              .getMergedProperties(
                  ceilingEntityFullyQualifiedClassname,
                  entities,
                  null,
                  persistencePerspective.getAdditionalNonPersistentProperties(),
                  persistencePerspective.getAdditionalForeignKeys(),
                  MergedPropertyType.PRIMARY,
                  persistencePerspective.getPopulateToOneFields(),
                  persistencePerspective.getIncludeFields(),
                  persistencePerspective.getExcludeFields(),
                  persistencePerspective.getConfigurationKey(),
                  "");
      Class<?>[] entities2 =
          persistenceManager.getPolymorphicEntities(
              adornedTargetList.getAdornedTargetEntityClassname());
      Map<String, FieldMetadata> mergedProperties =
          persistenceManager
              .getDynamicEntityDao()
              .getMergedProperties(
                  adornedTargetList.getAdornedTargetEntityClassname(),
                  entities2,
                  null,
                  new String[] {},
                  new ForeignKey[] {},
                  MergedPropertyType.ADORNEDTARGETLIST,
                  false,
                  new String[] {},
                  new String[] {},
                  null,
                  "");

      CriteriaTransferObject ctoInserted = new CriteriaTransferObject();
      FilterAndSortCriteria filterCriteriaInsertedLinked =
          ctoInserted.get(adornedTargetList.getCollectionFieldName());
      String linkedPath;
      String targetPath;
      if (adornedTargetList.getInverse()) {
        linkedPath =
            adornedTargetList.getTargetObjectPath() + "." + adornedTargetList.getTargetIdProperty();
        targetPath =
            adornedTargetList.getLinkedObjectPath() + "." + adornedTargetList.getLinkedIdProperty();
      } else {
        targetPath =
            adornedTargetList.getTargetObjectPath() + "." + adornedTargetList.getTargetIdProperty();
        linkedPath =
            adornedTargetList.getLinkedObjectPath() + "." + adornedTargetList.getLinkedIdProperty();
      }
      filterCriteriaInsertedLinked.setFilterValue(
          entity.findProperty(adornedTargetList.getInverse() ? targetPath : linkedPath).getValue());
      FilterAndSortCriteria filterCriteriaInsertedTarget =
          ctoInserted.get(adornedTargetList.getCollectionFieldName() + "Target");
      filterCriteriaInsertedTarget.setFilterValue(
          entity.findProperty(adornedTargetList.getInverse() ? linkedPath : targetPath).getValue());
      BaseCtoConverter ctoConverterInserted =
          getAdornedTargetCtoConverter(
              persistencePerspective, ctoInserted, mergedProperties, adornedTargetList);
      PersistentEntityCriteria queryCriteriaInserted =
          ctoConverterInserted.convert(
              ctoInserted, adornedTargetList.getAdornedTargetEntityClassname());
      List<Serializable> recordsInserted =
          persistenceManager
              .getDynamicEntityDao()
              .query(
                  queryCriteriaInserted,
                  Class.forName(adornedTargetList.getAdornedTargetEntityClassname()));
      if (recordsInserted.size() > 0) {
        payload =
            getRecords(
                mergedPropertiesTarget,
                recordsInserted,
                mergedProperties,
                adornedTargetList.getTargetObjectPath())[0];
      } else {
        Serializable instance = createPopulatedAdornedTargetInstance(adornedTargetList, entity);
        instance = createPopulatedInstance(instance, entity, mergedProperties, false);
        instance = createPopulatedInstance(instance, entity, mergedPropertiesTarget, false);
        FieldManager fieldManager = getFieldManager();
        if (fieldManager.getField(instance.getClass(), "id") != null) {
          fieldManager.setFieldValue(instance, "id", null);
        }
        if (adornedTargetList.getSortField() != null) {
          CriteriaTransferObject cto = new CriteriaTransferObject();
          FilterAndSortCriteria filterCriteria =
              cto.get(adornedTargetList.getCollectionFieldName());
          filterCriteria.setFilterValue(
              entity
                  .findProperty(adornedTargetList.getInverse() ? targetPath : linkedPath)
                  .getValue());
          FilterAndSortCriteria sortCriteria = cto.get(adornedTargetList.getSortField());
          sortCriteria.setSortAscending(adornedTargetList.getSortAscending());
          BaseCtoConverter ctoConverter =
              getAdornedTargetCtoConverter(
                  persistencePerspective, cto, mergedProperties, adornedTargetList);
          int totalRecords = getTotalRecords(persistencePackage, cto, ctoConverter);
          fieldManager.setFieldValue(
              instance, adornedTargetList.getSortField(), Long.valueOf(totalRecords + 1));
        }
        instance = persistenceManager.getDynamicEntityDao().merge(instance);
        persistenceManager.getDynamicEntityDao().flush();
        persistenceManager.getDynamicEntityDao().clear();

        List<Serializable> recordsInserted2 =
            persistenceManager
                .getDynamicEntityDao()
                .query(
                    queryCriteriaInserted,
                    Class.forName(adornedTargetList.getAdornedTargetEntityClassname()));

        payload =
            getRecords(
                mergedPropertiesTarget,
                recordsInserted2,
                mergedProperties,
                adornedTargetList.getTargetObjectPath())[0];
      }
    } catch (Exception e) {
      LOG.error("Problem editing entity", e);
      throw new ServiceException("Problem adding new entity : " + e.getMessage(), e);
    }

    return payload;
  }