class AbstractDynamoDao extends AbstractDao<M,P,K,I> {

    protected Item toCreateItem(P partial, Instant createAt, I creatorId) {
        Item item = partialMapper.toItem(partial);

        // add the @Id field (primary key)
        Field id = getFieldData().getId();
        if (id != null && item.get(id.getStorageName()) == null) {
            item.with(id.getStorageName(), toStorageValue(generatePrimaryKeyValue()));
        }

        // add the @CreatedAt and @CreatedBy fields
        Field createdByField = getFieldData().getCreatedBy();
        if (createdByField != null && item.get(createdByField.getStorageName()) == null && creatorId != null) {
            item.with(createdByField.getStorageName(), toStorageValue(creatorId));
        }
        Field createdAtField = getFieldData().getCreatedAt();
        if (createdAtField != null && item.get(createdAtField.getStorageName()) == null && createAt != null) {
            item.with(createdAtField.getStorageName(), toStorageValue(createAt));
        }
        // if @UpdatedAt and @UpdatedBy are non-optional, prepopulate them too
        Field updatedByField = getFieldData().getUpdatedBy();
        if (updatedByField != null && !updatedByField.isOptional() && item.get(updatedByField.getStorageName()) == null && creatorId != null) {
            item.with(updatedByField.getStorageName(), toStorageValue(creatorId));
        }
        Field updatedAtField = getFieldData().getUpdatedAt();
        if (updatedAtField != null && !updatedAtField.isOptional() && item.get(updatedAtField.getStorageName()) == null && createAt != null) {
            item.with(updatedAtField.getStorageName(), toStorageValue(createAt));
        }

        return item;
    }

    public  AbstractDynamoDao(Class<M> modelClass, Class<P> partialClass, AmazonDynamoDB db, String tableName);
    public  AbstractDynamoDao(Class<M> modelClass, Class<P> partialClass, AmazonDynamoDB db, String tableName, ItemMapper<M> modelMapper, ItemMapper<P> partialMapper);

}