I'm trying to use reordering feature of ace:tree component in icefaces. I have 3 types of nodes in my tree. My goal is to put some constraints on the tree.
Let's say i have node types A, B and C.
A is the root node
A can have only B type children
B can have children of type B or C
I want to block reordering when these constraints are not met. How one would apply such validation in ace:tree?
EDIT1
I forgot to mention that i have my validation implemented but what's not working is validation when using drag and drop feature (view updates to invalid state, model stays as it was when doing invalid operation) I need a clever way to refresh my view.
This can be done, without knowing how your code looks like, you have probably built your tree structure using nodes like
this one.
Therefore, you can constrain the data model (the parent nodes from the list) to accept only the values that you want.
You can signal to the user that an operation is not permitted using FacesMessage.
Related
I'm struggling to understand how to use UICollectionViewDiffableDataSource and NSDiffableDataSourceSnapshot to model change of items.
Let's say I have a simple item which looks like this:
struct Item {
var id: Int
var name: String
}
Based on the names of the generic parameters, UICollectionViewDiffableDataSource and NSDiffableDataSourceSnapshot should operate not with Item itself, but only with identifier, which Int in this example.
On the other hand, again based on names of generic parameters, UICollectionView.CellRegistration should operate on complete Item's. So my guess is that UICollectionViewDiffableDataSource.CellProvider is responsible for finding complete Item's by id. Which is unfortunate, because then aside from snapshots, I need to maintain a separate storage of items. And there is a risk that this storage may go out of sync with snapshots.
But it is still not clear to me how do I inform UICollectionViewDiffableDataSource that some item changed its name without changing its id. I want UICollectionView to update the relevant cell and animate change in content size, but I don't want insertion or removal animation.
There are two approaches that would work solve your problem in this scenario.
The first is to conform your Item model to the hashable protocol. This would allow you to use the entire model as an identifier, and the cell provider closure would pass you an object of type Item. UICollectionViewDiffableDataSource would use the hash value for each instance of your model (which would consider both the id and name properties, thereby solving your name changing issue) to identify the data for a cell. This is better than trying to trick the collection view data source into considering only the id as the identifier because, as you stated, other aspects of the model might change. The whole point of structs is to act as a value-type, where the composition of all the model's properties determine its 'value'...no need to trick the collection view data source into looking only at Item.id.
Do as you said, and create a separate dictionary in which you can retrieve the Items based on their id's. While it is slightly more work to maintain a dictionary, it is a fairly trivial difference in terms of lines of code. All you should do is dump and recalculate the dictionary every time you apply a new snapshot. In this case, to update a cell when the model changes, make sure to swap out the model in your dictionary and call reloadItem on your snapshot.
While the second option is generally my preferred choice because the point of diffable data source is to allow for the handling of massive data sets by only concerning the data source with a simple identifier for each item, in this case your model is so simple that there's really no concern about wasted compute time calculating hash values, etc. If you think your model is likely to grow over time, I would probably go with the dictionary approach.
Suppose I have two fluxes Flux<Class1> and Flux<Class2> and both Class1 and Class2 have a common attribute, say "id".
The use case is to join the two fluxes based on the common attribute "id" and construct a single Flux<Tuple<Class1, Class2>>, similar to joining two sql tables.
-There will always be a 1 to 1 match, for the attribute id, between the two fluxes.
-The fluxes won't contain more than 100 objects.
-The fluxes are not ordered by id.
How do I achieve this in Project Reactor/Spring web flux?
Assuming that:
both collections aren't very big (you can hold them in memory without risking OOM issues)
they're not sorted by id
each element in a collection has its counterpart in the other
First, you should make those Class1, Class2 implement Comparable or at least prepare a comparator implementation that you can use to sort them by their id.
Then you can use the zip operator for that:
Flux<Class1> flux1 = ...
Flux<Class2> flux2 = ...
Flux<Tuple2<Class1,Class2>> zipped = Flux.zip(flux1.sort(comparator1), flux2.sort(comparator2));
Tuple2 is a Reactor core class that lets you access each element of the Tuple like this
Tuple2<Class1,Class2> tuple = ...
Class1 klass1 = tuple.getT1();
Class2 klass2 = tuple.getT2();
In this case, sort will buffer all elements and this might cause memory/latency issues if the collections are large. Depending on how the ordering is done in those collections (let's say the ordering is not guaranteed, but those were batch inserted), you could also buffer some of them (using window) and do the sorting on each window (with sort).
Of course, ideally, being able to fetch both already sorted would avoid buffering data and would improve backpressure support in your application.
I think this should work with the following constraints:
the 2nd Flux needs to emit the same elements to all subscribers since it gets subscribed to over and over again.
this is basically the equivalent of a nested loop join so highly inefficient for large fluxes.
every element of the first Flux has a matching element in the second one.
flux1.flatMap(
f1 -> flux2.filter(f2 -> f2.id.equals(f1.id)).take(1)) // take the first with matching id
.map(f2 -> Tuple.of(f1,f2))) // convert to tuple.
writen without IDE. Consider pseudo code.
I've read this spring-data-rest tutorial https://spring.io/guides/gs/accessing-data-rest/ and I can't see how this can be applied in a real world situation where we don't have just one object, but a graph of objects.
Let's say that we have an Order object which has one-to-many relationship to an Item which is categorized by a Category object. Let's say for the sake of it, that the Category is implemented in a tree-like structure (so it has a parent and some children; i.e. an Electronic category could have 2 children, Computer and TV, the former having another two children, motherboard and keyboards).
And let's say that all these relation are two ways (i.e. an Order can see it's items and an Item can access it's Order)
So when I request an Order object threw my REST service, I'm gone get the Order, all it's Items and each Item will have the whole graph of Category which will be linked to each Item and thus all the orders. So I'm basically returning the whole database.
I do understand that the bidirectional relations is not ideal but even if we suppress the many side of the relationship, when requesting an Order, we would still get
Order-Item-Category-Parent Category-Parent of Parent Category-etc...
So how do you stop a graph of objects being serialized?
Furthermore, you might not want to break the graph at a fix point.
For instance when I request an Order, I might want to see it's items and the category of each item, but definitely not the parent's category.
However, when I want to explicitly display a Category, I would then like to see it's parent. Get it?
Does somebody have some insight for me?
This is where DTOs are a good thing. :)
You build the object structure you need and return it via json. You have full control over this structure, you dont have bidirectional relations and you can just give that back as an object graph from your controller.
Another (good) side effect is that you decouple persistence and view completely. I.e both can evolve independently.
One (negative) side effect can be the increased maintenance. You have, at least, twice the classes to maintain and also the mapping in between. Frameworks like Dozer can help you with the mapping at least.
Another solution can be to implement some addons for Jackson that handle all these cases without the need of DTOs.
I myself created the Antpath filter to dynamically decide which path to filter out in Jackson:
https://github.com/Antibrumm/jackson-antpathfilter
But you will need some more things to consider if you like to work with domain entities directly.
cycle breaker (to avoid bidirectional relations for example)
lazy loading / open session in view pattern as the serialization can go everywhere
hibernate proxies which have method which are not serializable (session)
I'm hoping to write an algorithm to synchronize two hierarchical structures. These structures could be object graphs, data stored in relational database tables, etc (even two different structures, so long as they have comparable keys). The synchronization will be one-way, i.e., one structure will be the prototype, and the other will be modified to match.
Let's say we have a sync function. It would need to accept the following:
objA -- the prototype
objB -- the object to be modified
keyA -- key generating function for objA
keyB -- key generating function for objB
addB -- function to create an objB (returns id of new objB)
setB -- function to update objB
remB -- function to delete an objB
parB -- id of objB's parent -- this is passed to addB for context
So we have this:
let sync (objA:'a) (objB:'b) (keyA:'a -> 'k) (keyB:'b -> 'k)
(addB:'p * 'a -> 'p) (setB:'a * 'b -> unit) (remB:'b -> unit)
(parB:'p) = ...
Now here's where I'm having trouble. 'a and 'b are hierarchical, so the function needs to know which properties of 'a and 'b it should traverse (once it compares their keys and decides they match thus far and should be further traversed). For these "child" properties, it needs all the same arguments passed to sync, but for their respective types.
This is when it became apparent this is a data structure problem. How can I chain together this information such that the root object can be passed to sync and it can traverse the graphs downward? My initial thought was to incorporate all of the arguments into a class, which would have a children property (a ResizeArray of the same type). But with various properties having different types, I couldn't figure out a way to make it work, short of throwing types out the window and making most or all of the type arguments obj.
So here are my questions:
Is there a well-established method for doing this already (I haven't been able to find anything)
What data structure might I use to encapsulate the data necessary to make this work?
I've tried my best to explain this thoroughly, but if anything remains unclear, please ask, and I'll try to provide better information.
I'm sure this is oversimplifying it but here's my idea.
If this is a DAG you could do a breadth-first traversal of objA. When you enqueue a node from objA include objB and any other information you need (tuple). Then when you dequeue you fix up objB.
You could use a discriminated union to handle different child types in your enqueueing.
Generate diffgrams from the two data structures and map the transforms to the transformed problem.
I have a model and two views set up like this:
Model ---> OSortFilterProxyModel ---> OListView
Model ------------------------------> OTableView
When the user selects something in one of the views, I want the other view to mirror that selection. So I thought I'd use a QSelectionModel to link them together. But this does not work. I have a feeling it is because the views think they have two different models, when in fact they have the same model. Is there a way to get this to work?
What is probably happening is that the views do have two different models. One is your original model, the other is the sort filter model.
I'm not sure if this would work, and it depends on what Qt considers "activated", but you could connect a function to each of the view's activated slots. These will pass you a model index. You'll have to send the model index through the proxy model in the appropriate direction (mapFromSource and mapToSource). Then, call the setCurrentIndex on the other view.
The documentation for the activated signal states that what is considered "activated" varies by platform. There might be other signals you could latch onto, such as the selection model's selection changed signal. You might have to do a different call to change the selection as seen by the user. And finally, it might be possible or even easier to do in a derived QSelectionModel, as long as you remember about mapping to/from the source model.
Not quite sure how your model subclass is implemented - but the selection depends on persistent model indexes being correct. Can you provide some source code? Are you using the same selection model on both?
You propably need to use void QItemSelectionModel::select combined with QAbstractProxyModel::mapSelectionFromSource and QAbstractProxyModel::mapSelectionToSource. In QListView's selectionChange signal handler you should have
tableView->selection()->select(
proxyModel->mapSelectionToSource(selected),
QItemSelectionModel::ClearAndSelect);
and analogically with mapSelectionFromSource in QTableView's signalChange signal handler.
Note that i am not sure if Qt will prevent infinite recursion when table will change selection of list which in turn will change selection of table and so on...