Page 1 of 1

Getting metadata to the Form?

Posted: Sun Feb 02, 2014 10:28 am
by RapidTransit
So I needed something to help me manipulate the Admin forms a little easier,

I made an annotation with AngularJS attribute declarations, so I extended FieldMetaDataProviderAdapter upon getting invoked my values get added to additionalMetadata (Confirmed in my debug console)

Code: Select all

    <bean id="blMetadataProviders" class="org.broadleafcommerce.common.util.SortedListFactoryBean" scope="prototype">
        <property name="sourceList">
            <list>
                <ref bean="blBasicFieldMetadataProvider"/>
                <ref bean="blAngularJSMetadataProvider" />
                <ref bean="blCollectionFieldMetadataProvider"/>
                <ref bean="blAdornedTargetCollectionFieldMetadataProvider"/>
                <ref bean="blMapFieldMetadataProvider"/>
                <ref bean="blMapFieldsFieldMetadataProvider"/>
                <ref bean="blPasswordFieldMetadataProvider"/>
            </list>
        </property>
    </bean>

Code: Select all

@Component("blAngularJSMetadataProvider")
@Scope("prototype")
public class AngularJSMetadataProvider extends FieldMetadataProviderAdapter{

    protected boolean canHandleFieldForConfiguredMetadata(AddMetadataRequest addMetadataRequest) {
        AngularJS annotation = addMetadataRequest.getRequestedField().getAnnotation(AngularJS.class);
        return annotation != null;
    }

    @Override
    public FieldProviderResponse addMetadata(AddMetadataRequest addMetadataRequest, Map<String, FieldMetadata> metadata) {
        if (!canHandleFieldForConfiguredMetadata(addMetadataRequest)) {
            return FieldProviderResponse.NOT_HANDLED;
        }
        AngularJS annotation = addMetadataRequest.getRequestedField().getAnnotation(AngularJS.class);
        FieldInfo fieldInfo = buildFieldInfo(addMetadataRequest.getRequestedField());
        Map<String, Object> annotationAttributes = AnnotationUtils.getAnnotationAttributes(annotation);
        Map<String, Object> annotationAttributesFixed = new HashMap<String, Object>();
        for(Map.Entry<String, Object> annotationAttribute: annotationAttributes.entrySet())
        {
            if(!annotationAttribute.getValue().toString().isEmpty())
            {
                String lc = annotationAttribute.getKey().toLowerCase();
                String dash = lc.replace("ng", "ng-");
                annotationAttributesFixed.put(dash, annotationAttribute.getValue());
            }
        }
        String ngCsv = Joiner.on(",").withKeyValueSeparator("=").join(annotationAttributesFixed);
        buildBasicMetadata(metadata, fieldInfo, ngCsv);
        return FieldProviderResponse.HANDLED;
    }

    protected void buildBasicMetadata(Map<String, FieldMetadata> attributes, FieldInfo field, String ngCsv) {
        BasicFieldMetadata serverMetadata = (BasicFieldMetadata) attributes.get(field.getName());
        BasicFieldMetadata metadata;
        if (serverMetadata != null) {
            metadata = serverMetadata;
        } else {
            metadata = new BasicFieldMetadata();
        }
        Map<String, Object> addMeta = new HashMap<String, Object>();
        addMeta.put("angular", ngCsv);
        metadata.setAdditionalMetadata(addMeta);
        attributes.put(field.getName(), metadata);
    }
}

I've overridden blAdminWebCustomTemplateResolver to point to my directory and set it at the highest precedence.

Code: Select all

    <bean id="blAdminWebCustomTemplateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
        <property name="prefix" value="/WEB-INF/admin/templates/" />
        <property name="suffix" value=".html" />
        <property name="templateMode" value="HTML5" />
        <property name="characterEncoding" value="UTF-8" />
        <property name="cacheable" value="${cache.page.templates}"/>
        <property name="cacheTTLMs" value="${cache.page.templates.ttl}" />
        <property name="order" value="100"/>
    </bean>

But the value doesn't exist when I added it to the overridden field template. It just throws a Thymeleaf Exception.
My next thought is extend AbstractFormBuilderExtensionHandler am I on the right track?

Code: Select all

    <bean id="blFormBuilderExtensionHandlers" class="org.springframework.beans.factory.config.ListFactoryBean" >
        <property name="sourceList">
            <list>
                <ref bean="blAngularJSFormBuilderExtensionHandler" />
            </list>
        </property>
    </bean>

Re: Getting metadata to the Form?

Posted: Sun Feb 02, 2014 3:07 pm
by RapidTransit
Taking another look maybe it's the CustomPersistenceHandler that I'm after?

Re: Getting metadata to the Form?

Posted: Tue Feb 11, 2014 6:36 pm
by RapidTransit
Bumping still can't figure if I should use FormBuilderExtensionHandler or CustomPersistenceHandler, almost looks like I could use either.

Re: Getting metadata to the Form?

Posted: Tue Feb 11, 2014 7:47 pm
by phillipuniverse
True, you could use either.

I think since you are wanting to use introspection on the entity annotations you should use the custom persistence handler. The FormBuilderExtensionHandler is more for after all of the metadata has been built and added to the EntityForm DTO object to be displayed on the page. At this point, the assumption is everything to do with your Hibernate entities has been finished and you need a couple of final customizations before it's displayed, dealing only with display attributes.

What do you mean that the value doesn't exist when you added it to the overridden field template?

Re: Getting metadata to the Form?

Posted: Tue Feb 11, 2014 7:55 pm
by phillipuniverse
Actually, the metadata provider that you added seems pretty appropriate for what you're trying to do. Are you sure that it's actually being invoked?

Also, it looks like you're adding attributes to the 'additionalMetadata' map on BasicFieldMetadata, which might be designed originally to appear on the 'attributes' map on Field but it doesn't look like that's happening at the moment.

Can you provide a little more details on this line of thinking and open an issue at https://github.com/BroadleafCommerce/Br ... rce/issues

Re: Getting metadata to the Form?

Posted: Tue Feb 11, 2014 8:29 pm
by RapidTransit
I set a break point at line 781 on DynamicEntityDaoImpl, under presentationAttributes my additionalMetaData is still there, then from around there it disappears, and doesn't become available to the template engine. Edit: It exists under the variable myField (Reflected Field) . Also For some reason ProductImpl gets loaded and thrown through DynamicEntityDaoImpl in every module.