Conditions in Alfresco policies binding - alfresco

I have OnCreateNodePolicy implementation and I'm thinking about adding conditions in binding initialization (some optimalizations for speed), is it possible?
What do I mean? Let's have definition similar to this:
policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"),
ContentModel.TYPE_CONTENT, onCreateNode);
Now when node is created, mine onCreateNode() is called. First thing I do is to check, if my parent has some aspect. Isn't it possible to add this condition into binding definition? So onCreateNode() is called only when this condition is met?

You can not add conditions to the binding definition but in your case you could consider using the OnCreateChildAssociationPolicy instead of the OnCreateNodePolicy. The advantage is that you could bind it to your custom aspect. It would look something like this:
policyComponent.bindAssociationBehaviour(
NodeServicePolicies.OnCreateChildAssociationPolicy.QNAME,
YourCustomModel.ASPECT_YOURASPECT,
ContentModel.ASSOC_CONTAINS,
new JavaBehaviour(this, "onCreateChildAssociation", NotificationFrequency.TRANSACTION_COMMIT)
);
You have to keep in mind though that child associations are also created when you move a node to a new folder, not only when you create it. Also you now have to check the type of the child node (ContentModel.TYPE_CONTENT) in your Java code.

Related

Is overriding JavaFx TreeItem getChildren add a good idea?

My aim is to have a process done during all addition to children in a Tree (a TableTreeView to be precise).
The node.getTreeItem().getChildren.add(playlist) is called in different parts of my code, and I tried to keep best practices as much as possible... so let's keep it simple and say I will for sure call it while a drag'n'drop is done, as well as at the building of the tree.
My 'playlist' can be of 3 different types (in enum class) :
FOLDER (containing other playlist)
LIST (containing tracks added by user)
QUERY (containing tracks as result of a query)
MISTAKE (should never be set, but useful for debug and so)
I want to implement a method on my 'extended' TreeItem<Playlist> such as getPlaylistType().
This method would return the type of the playlist.
QUESTION :
My instinct would say I should Override the node.getTreeItem().getChildren.add(playlist) to set the type in a way :
There are children playlist --> FOLDER
No children playlist && query exists --> QUERY
No children playlist && query does not exists --> LIST
Any other state --> UNKOWN/MISTAKE
Is this approach correct ?
How to Override the 'add(...)' method ?
Why do you expose node.getTreeItem().getChildren.add(playlist) to different parts of your software? If you just wrap it in your own class you could expose that and do whatever you want when the corresponding add method is called.

How do you manage adding new attributes on existing objects when using firebase?

I have an app using React + Redux and coupled with Firebase for the backend.
Often times, I will want to add some new attributes to existing objects.
When doing so, existing objects won't get the attribute until they're modified with the new version of the app that handles those new attributes.
For example, let's say I have a /categories/ node, in there I've got objects such as this :
{
name: "Medical"
}
Now let's say I want to add an icon field with a default of "
Is it possible to update all categories at once so that field always exists with the default value?
Or do you handle this in the client code?
Right now I'm always testing the values to see if they're here or not, but it doesn't seem like a very good way to go about it. I'd like to have one place to define defaults.
It seems like having classes for each object type would be interesting but I'm not sure how to go about this in Redux.
Do you just use the reducer to turn all categories into class instances when you fetch them for example? I'm worried this would be heavy performance wise.
Any write operation to the Firebase Database requires that you know the exact path to the node that you're writing.
There is no built-in operation to bulk update nodes with a path that is only partially known.
You can either keep your client-side code robust enough to handle the missing properties, or you can indeed run a migration script to add the new property to each relevant node. But since that script will have to know the exact path of each node to write, it will likely first have to read/query the database to determine those paths. Depending on the number of items to update, it could possibly use multi-location updates after that to update multiple nodes in one call. E.g.
firebase.database().ref("categories").update({
"idOfMedicalCategory/icon": "newIconForMedical",
"idOfCommercialCategory/icon": "newIconForCommercial"
"idOfTechCategory/icon": "newIconForTech"
})

How to override record table naming to access existing data in Orchard CMS

I need to access data from pre-existing tables. I've started working my way through creating a module to display the data etc. However, Orchard is prefixing the table commands with the 'Table_Prefix' and 'Module Name'.
Is there any way I can specify what table to bind the model, so that I can use the existing IRepository
I'm trying to steer clear of modifying the core code, or implement my own IRepository ( which I've got a feeling is what I'm going to have to do.)
Thanks in advance.
You can create custom table naming convention (so that it would fit your current naming) by altering the core code, in three ways:
Record name mapping is created in BuildRecord method of
CompositionStrategy class
(Orchard.Framework/Environment/ShellBuilders/CompositionStrategy), so you can simply modify the code here.
By altering the Apply method of Orchard.Data.Conventions.RecordTableNameConvention class. This is where the record table name mappings (built in point 1.) get pushed to NHibernate.
Create your own implementation of FluentNHibernate.Conventions.IClassConvention (similar to RecordTableNameConvention mentioned above and replace the default one used by AutoMap in Orchard.Data.Providers.AbstractDataServicesProvider's CreatePersistenceModel(...) method with it.
You could also create your own IDataServicesProvider implementation, but that would surely be an overkill if you only need to change the table naming convention.
I was modifying CompositionStrategy and discovered that you have to modify the following
1. SetupService.cs (Modules\Orchard.Setup\Services):
Tables hardcoded in the Setup method are
"Orchard_Framework_DataMigrationRecord" and
"Settings_ShellDescriptorRecord"
2. InfosetController.cs (Modules\Upgrade\Controllers):
Multiple tables were hardcoded in this class which need to be updated.
3. DataMigrationManager.cs (Data\Migration):
Replace the SchemaBuilder parameters to the contructor.

React to change on a static property

I'm re-writing an MXML item renderer in pure AS. A problem I can't seem to get past is how to have each item renderer react to a change on a static property on the item renderer class. In the MXML version, I have the following binding set up on the item renderer:
instanceProperty={callInstanceFunction(ItemRenderer.staticProperty)}
What would be the equivalent way of setting this up in AS (using BindingUtils, I assume)?
UPDATE:
So I thought the following wasn't working, but it appears as if Flex is suppressing errors thrown in the instanceFunction, making it appear as if the binding itself is bad.
BindingUtils.bindSetter(instanceFunction, ItemRenderer, "staticProperty");
However, when instanceFunction is called, already initialized variables on the given instance are all null, which was the cause of the errors referenced above. Any ideas why this is?
You have 2 options that I am aware of:
Option 1
You can dig into the code that the flex compiler builds based on your MXML to see how it handles binding to static properties. There is a compiler directive called -keep-generated-actionscript that will cause generated files to stick around. Sleuthing through these can give you an idea what happens. This option will involve instantiating Binding objects and StaticPropertyWatcher objects.
Option 2
There is staticEventDispatcher object that gets added at build time to classes containing static variables see this post http://thecomcor.blogspot.com/2008/07/adobe-flex-undocumented-buildin.html. According to the post, this object only gets added based on the presence of static variables and not getter functions.
Example of Option 2
Say we have a class named MyClassContainingStaticVariable with a static variable named MyStaticVariable and another variable someobject.somearrayproperty that we want to get updated whenever MyStaticVariable changes.
Class(MyClassContainingStaticVariable).staticEventDispatcher.addEventListener(
PropertyChangeEvent.PROPERTY_CHANGE,
function(event:PropertyChangeEvent):void
{
if(event.property == "MyStaticVariable")
{
someobject.somearrayproperty = event.newValue as Array;
}
});
I think you need to respond to the "PropertyChanged" event.
If you're going to do that, use a singleton instead of static. I don't think it will work on a static. (If you have to do it that way at all, there are probably a couple ways you could reapproach this that would be better).
var instance:ItemRenderer = ItemRenderer.getInstance();
BindingUtils.bindProperty(this, "myProperty", instance, "theirProperty");
After fiddling with this for a while, I have concluded that this currently isn't possible in ActionScript, not even with bindSetter. It seems there are some MXML-only features of data bindings judging by the following excerpt from the Adobe docs (though isn't it all compiled to AS code anyways)?
You cannot include functions or array
elements in property chains in a data
binding expression defined by the
bindProperty() or bindSetter() method.
For more information on property
chains, see Working with bindable
property chains.
Source: http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_7.html
You can create a HostProxy class to stand in for the funciton call. Sort of like a HostFunctionProxy class which extends from proxy, and has a getProperty("functionInvokeStringWithParameters") which will invoke the function remotely from the host, and dispatch a "change" event to trigger the binding in typical [Bindable("change")] Proxy class.
You than let the HostProxy class act as the host, and use the property to remotely trigger the function call. Of course, it'd be cooler to have some TypeHelperUtil to allow converting raw string values to serialized type values at runtime for method parameters (splitted by commas usually).
Example:
eg.
var standInHost:Object = new HostFunctionProxy(someModelClassWithMethod, "theMethodToCall(20,11)");
// With BindingUtils.....
// bind host: standInHost
// bind property: "theMethodToCall(20,11)"
Of course, you nee to create such a utlity to help support such functionality beyond the basic Flex prescription. It seems many of such (more advanced) Flex bindings are usually done at compile time, but now you have to create code to do this at runtime in a completely cross-platform Actionscript manner without relying on the Flex framework.

Accessing other templates' instances

You can access the current template's instance by doing Template.instance(). But you often run into situations where you have to access other templates' instances as well. For example, if you use ReactiveVar, then you would want to get or set variables that are attached to other template instances.
I came across How to get the parent template instance (of the current template) but this is not complete.
Q1. How can we access any template's instance, not just the current template's
Q2. Is it against the Meteor way if I need to access other templates' instances?
you can try to set your template variable directly at the template level instead of inside the instance.
Template.example.myVariable = new ReactiveVar();
instead of
Template.example.onCreated(function (){
this.myVariable = new ReactiveVar();
});
The closest I got was to target the template by one of its elements (assume the template contains a form)
Blaze.getView($('form')[0]).templateInstance().someReactiveVar.set('changed')
If your target templates are in the same file, you can just define the reactive variable outside the template functions, at the beginning of the file. All templates in the file will access it.
If your target template is the parent template, (or any further parent template) you can access its data context using Template.parentData() the argument being the rank of the parent (default is 1). It seems that you know that already.
If you need to access a DOM element within a different template in the same page, you can use jQuery selectors.
I don't know any other way to reach another template instance (afaik, there is no Blaze.getTemplate(name) function.) The answer you are referring to seems to be the better you can get.
I think this is purely subjective, since in Meteor there are so many different ways of doing things, but I actually think Session is perfectly suited for sharing variables across several templates. People argue that Session is bad since it's global and can pollute the namespace. I would argue that it's up to the developer to keep their environment clean in any way that works for them. So for instance, this is bad:
Session.set('count', 23);
Session.set('last', new Date());
But this is better:
Session.set('notifications/count', 23);
Session.set('notificatinos/last', new Date());

Resources