Good Day
I am attempting to use castor to construct a HashTable that has multiple implementations of an abstract class.
here is the parent "config"
<class name="com.Config">
<map-to xml="config" />
<field name="rulesMap" collection="hashtable">
<bind-xml auto-naming="deriveByClass" >
<class name="org.exolab.castor.mapping.MapItem">
<field name="key" type="java.lang.String">
<bind-xml name="name" node="attribute" />
</field>
<field name="value" type=com.Rule">
</field>
</class>
</bind-xml>
</field>
</class>
'com.Rule' is an Abstract Class and
at the end of the day i would like an xml struct that looks like this
<config>
<rule-impl1 name="ruleType1Instance1" ruleField="field" />
<rule-impl2 name="ruleType2Instance2" ruleField="field" ruleImpl2Field1="..." />
</config>
I'm not sure there is enough detail or a question that is well formed here to give an accurate answer, but I was doing something pretty similar and ran into some roadblocks. Thought I'd provide my 2 cents. I'm not as familiar with Castor as I am some other XML frameworks and in my case Castor is doing it's automatic marshalling/unmarshalling instead of us manually writing the code to decide when we want it to be done. If we were manually doing that piece I thought we would have been able to make decisions to unmarshall to specific classes that extend the abstract class.
With all my disclaimers out of the way, what you could do.
**If you can add a field to the request/response then create something like this:
public class RuleContainer {
private RuleType ruleType; // possibly build enum or other non-java equivalent
private RuleImpl1 ruleImpl1;
private RuleImpl2 ruleImpl2;
private RuleImpl...N ruleImpl...N;
// getters & setters, etc
}
Then the value of your table is changed to
<field name="value" type="com.RuleContainer"></field>
and include your mapping of the RuleContainer
<class name="com.RuleContainer">
<field name="ruleType" type="com.RuleType"
<field name="ruleImpl1" type="com.RuleImpl1">
<field name="ruleImpl2" type="com.RuleImpl2">
<field name="ruleImpl...N" type="com.RuleImpl...N">
</class>
also include mappings of each implementation whatever those may look like. In my case I've broken each implementation mapping out into a separate file and used the
<include href="" />
tag to include those extraneous mappings in the parent file.
All of this sets you up to use that RuleType field to know which rule in the RuleContainer is valid (the rest will be null as the Castor default is required="false"). The logic to work with each implementation of a Rule is simple to write from there.
Hope this helps.
Related
I have been trying to validate my alfresco share workflow form for several days without success. This is what i have done.
Configured my workflow in the share-config-custom.xml located in %TOMCAT_HOME%tomcat\shared\classes\alfresco\web-extension
set my contraint handler as follows.
<constraint-handlers>
<constraint type="MANDATORY"
validation-handler="Alfresco.forms.validation.examplestaffnumber"
event="keyup" />
</constraint-handlers>
</field>
This field i have set to mandatory
< label-id="Staff Number" id="leave:staffnumber" mandatory="true">
I have created the contraint hanlder javascript and placed it at %ALFRESCO_HOME%\tomcat\webapps\share\js folder. This is both js and min.js
Finaly added the js in form.get.head.ftl located at %ALFRESCO_HOME%tomcat\webapps\share\WEB-INF\classes\alfresco\site-webscripts\org\alfresco\components\form
folder like this
<#script type="text/javascript" src="${page.url.context}/res/js/examplevalidation.js">
When I select my worflow form and key values in the staff number form nothing happens. I have checked in the firebug but there is no any call to the js.
Where could i have gone wrong?
I think you have not added dependencies for your java script. To do that add below code in your share-config-custom.xml located in %ALFRESCO_HOME%tomcat\shared\classes\alfresco\web-extension
<config>
<forms>
<dependencies>
<js src="/js/examplevalidation.js" />
</dependencies>
</forms>
</config>
And your constrains handler should be like
<field id="leave:staffnumber" label-id="Staff Number" mandatory="true">
<control template="/org/alfresco/components/form/controls/textfield.ftl" />
<constraint-handlers>
<constraint type="MANDATORY" validation-handler="Alfresco.forms.validation.examplestaffnumber" event="blur"/>
</constraint-handlers>
</field>
And function in your js should be like this:
Alfresco.forms.validation.examplestaffnumber = function examplestaffnumber(
field, args, event, form, silent, message) {
// your code with return statement
}
Hope this helps!!!
How can I add multiselect field to a dexterity content type via model xml file? It is clear how to add single selection dropdown field:
<field name="dummy" type="zope.schema.Choice">
...
<source>plone.supermodel.tests.dummy_binder</source>
</field>
But how to do multi-select field? Basically the same as I can get with this python (zope schema):
my_field = schema.List(
title="A title",
value_type=schema.Choice(source='some.source.vocabulary'),
required=True
)
There is no problem for me to use python way, I'm just curious how to achieve this with xml.
Thanks,
Rapolas
A value_type tag:
<field name="links" type="zope.schema.List">
<title>Related Items</title>
<value_type type="zope.schema.Choice">
<title>Related</title>
<source>plone.supermodel.tests.dummy_binder</source>
</value_type>
</field>
Your source should implement IContextSourceBinder.
I have a custom content type, built with dexterity. In the schema (The schema is listed below), I use 'plone.namedfile.field.NamedFile' for attachements/uploads.
I would like to restrict uploads so that only mp3 files can be attached to my content type. What is the best approach for achieving this?
Here is the full schema/model for my content type:
<model xmlns="http://namespaces.plone.org/supermodel/schema">
<schema>
<field name="date" type="zope.schema.Date">
<description />
<title>Date</title>
</field>
<field name="speaker" type="zope.schema.TextLine">
<description />
<title>Speaker</title>
</field>
<field name="service" type="zope.schema.Choice">
<description />
<title>Service</title>
<values>
<element>1st Service</element>
<element>2nd Service</element>
</values>
</field>
<field name="audio_file" type="plone.namedfile.field.NamedFile">
<description />
<title>Audio File</title>
</field>
</schema>
</model>
I shall begin my search here: http://plone.org/products/dexterity/documentation/manual/developer-manual/reference/default-value-validator-adaptors
I've decided to use javascript for my first line of validation.
I've based my solution on information found at <input type="file"> limit selectable files by extensions
Based on the advice my script looks something like this:
$(document).ready( function() {
function checkFile(event) {
var fileElement = document.getElementById("form-widgets-audio_file-input");
var fileExtension = "";
if (fileElement.value.lastIndexOf(".") > 0) {
fileExtension = fileElement.value.substring(fileElement.value.lastIndexOf(".") + 1, fileElement.value.length);
}
if (fileExtension == "mp3") {
return true;
}
else {
alert("You must select a mp3 file for upload");
return false;
}
}
$("form#form").bind("submit",checkFile);
});
This is half the solution, next I'll need to add validation on the server side.
<#list flowList as flow>
<#spring.formInput "flow.createDatetime" />
</#list>
flowList is arrayList.
freemarker.template.TemplateModelException: Method public org.springframework.web.servlet.support.BindStatus org.springframework.web.servlet.support.RequestContext.getBindStatus(java.lang.String) throws java.lang.IllegalStateException threw an exception when invoked on org.springframework.web.servlet.support.RequestContext#8bc713e with arguments of types [java.lang.String,]
at freemarker.ext.beans.OverloadedMethodModel.exec(OverloadedMethodModel.java:134)
at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:93)
How can I resolve #spring.formInput in #list.
Have you tried doing an intermediate assign? I saw this problem on other StackOverflow pages, like Freemarker syntax for a form for a collection of objects (Spring 3 MVC):
<#list flowList as flow>
<#assign flowDate = flow.createDatetime />
<#spring.formInput "flowDate" />
<\#list>
The following workaround works for me, but is pretty ugly:
<#list flowList as flow>
<#assign index=flowList?seq_index_of(flow)>
<#spring.formInput "flowList[${index}].createDatetime" />
</#list>
When the above form is posted, you'll need to ensure that the flow-list is pre-populated with empty flows. Alternatively, just using Spring's AutoPopulatingList as the flow-list implementation.
For spring to bind the object, the exact reference must be provided. Hence you need to add the index in the tag. This is needed when you post the form back and want the flowlist object as request body in a controller method.
<#list flowList as flow>
<#spring.formInput "flowList[${flow_index}].createDatetime" />
</#list>
After rendering if you look at the HTML it would be like
<input type="text" id="flowList0.createDatetime" name="flowList[0].createDatetime" value="..." />
I have a 'Photo' class and a 'Comment' class. An Photo can have multiple comments assigned to it.
I have this configured as a one-to-many relationship within my HBM mapping file, and have set cascade="all-delete-orphan" against the 'Comments' bag within the Photo.hbm.xml mapping file.
However, if I try to delete a Photo which has 1 or more Comments associated with it, I am getting 'The DELETE statement conflicted with the REFERENCE constraint "FK_Comments_Photos"'
I tried a couple of other cascade options against the Comments bag in my Photo.hbm.xml but regardless of what I set it to, I'm getting the same outcome each time. I just want to be able to delete a Photo and have any associated comments automatically delete too.
Here is my Photo mapping (edited for brevity):
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" .... default-access="property" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" name="Photo" table="Photos">
<id name="PhotoId" unsaved-value="0">
<column name="PhotoId" />
<generator class="native" />
</id>
...
<bag name="Comments" table="Comments" cascade="all-delete-orphan" order-by="DateTimePosted desc" where="Approved=1">
<key column="PhotoId" />
<one-to-many class="Comment" />
</bag>
</class>
Here is my Comment mapping (edited for brevity):
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" ... default-access="property" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" name="Comment" table="Comments">
<id name="CommentId" unsaved-value="0">
<column name="CommentId"></column>
<generator class="native" />
</id>
...
<property name="Author" not-null="true" />
<property name="Body" not-null="true" />
<property name="Approved" not-null="true" />
<many-to-one name="Photo" not-null="true">
<column name="PhotoId" />
</many-to-one>
</class>
Does anyone have any suggestions as to why the cascade is not happening when I try to delete a Photo with comments associated with it?
UPDATE: The only way I can get the cascade to happen is to configure the 'Delete Rule' within SQL Server against this relationship to 'Cascade', and in doing so means that I don't need to specify any cascade action within my NHibernate Mapping. However, this isn't ideal for me - I'd like to be able to configure the cascade behaviour within the NHibernate Mapping ideally, so I'm still confused as to why it doesn't appear to be taking any notice of my NHibernate cascade setting?
My guess would be that the problem comes from the fact that the many-to-one in the Comment mapping is set to not-null="true".
Because of that, NHibernate is not allowed to set this property to null temporarily before it deletes the Photo object and therefore when is goes about deleting the Photo object SQL Server throws an foreign key exception.
If I remember correctly for the order of actions when deleting is:
Set foreign key value to null in all child objects
Delete parent object
Delete all child references
Try to remove the not-null="true" from the many-to-one and see what will happen.
Try with inverse="true" on the bag collection of your mapping.
I had similar problem for 1 day .. and got frustrated over it.
Finally the solution boiled down to the DB.
I had to change the FK key constraints in "INSERT UPDATE SPECIFICATION"
'Delete Rule' : from 'No Action' to 'Cascade'
additionally you can also set
'Update Rule' : from 'No Action' to 'Cascade'
You can specify the delete-cascade option in NH:
<bag name="Comments" cascade="all-delete-orphan" order-by="DateTimePosted desc" where="Approved=1">
<key column="PhotoId" on-delete="cascade"/>
<one-to-many class="Comment" />
</bag>
You probably should make it inverse. Then I wonder where your FK_Comments_Photos column is specified.