I am new to ATg commerce world and was wondering if someone can help me with an issue. We have Additional properties for our CommerceItem. Once a user logs into our website, these additional properties of the commerceItem are not getting copied over. Can someone advise or give an example as to how can i make sure that the properties are copied over?
Below is a snippet of my code:
CommerceItem sourceCitem;
CommerceItem destCitem;
List citemList = pSrcOrder.getCommerceItems(); //get commerce item from source order
for (int i = 0, citemListSize = citemList .size(); i < citemListSize; i++) {
sourceCitem= (CommerceItem) ciList.get(i);
destCitem= getCommerceItemManager().mergeOrdersCopyCommerceItem(pSrcOrder,pDestOrder, sourceCitem);
I extended CommerceItemImpl and added all additional properties in the new class which are not getting added to destCitem.
Any help will be appreciated.
Thanks
You need to subclass CommerceItemManager and override the mergeOrdersCopyCommerceItem method to first call the superclass method to do the basic copy and then copy your extended commerce item data.
For e.g:
protected CommerceItem mergeOrdersCopyCommerceItem(Order pSrcOrder, Order pDstOrder, CommerceItem pItem) throws CommerceException {
NewCommerceItem item = (NewCommerceItem) pItem;
NewCommerceItem newItem = (NewCommerceItem) super.mergeOrdersCopyCommerceItem(pSrcOrder, pDstOrder, pItem);
//Now your code to add the changes.
newItem.setABC(item.getABC());
return newItem;
}
And, as the change you have already done, so it's all we need.
Related
Background
I am trying to create an immutable object that contains a list of immutable objects, as well as object type totals within the list.
I created a slightly sudo gist to try and show what I mean.
Gist - Adjusting an immutable object that contains an immutable object list.
Explanation
My example shows how I'm currently doing it, it does work. However not for all cases.
My VeggieCartView will have a recyclerview that gets filled with a new/saved VeggieCart.
Each VeggieCart has a list of veggies. Veggie totals etc...
I then have a helper class VeggieChanger, it contains an rx.Consumer<Veggie[]> that gets set and accepts any 1:1 veggie changes from the veggie views.
The VeggieCartView sets the consumer so when any one veggie changes, it creates an updated cart using the changes' corresponding cart factory method. The adapter is used to change/retrieve its list.
Working and not
This works well for changing one at a time, however batching changes is throwing concurrency exceptions.
I realize my gist is not runnable and doesn't show most boilerplate, and that I may be fundamentally wrong with some or all of my approaches. With that said I still hope someone can give me advice on how to better implement what I'm trying to do.
If more information is needed to understand, please ask. Thank you for anybody who does have help to offer,
Jon.
I ended up figuring out my main issue.
By adding this to my VeggieCartView:
public void bagAllCanned() {
final Veggie[] canned = new Veggie[cart.canTotal()];
final Veggie[] bagged = new Veggie[canned.length];
int t = 0;
final List<Veggie> veggies = cart.veggies();
for (int i = 0; i < veggies.size(); i++) {
final Veggie veggie = veggies.get(i);
if (veggie.canned()) {
canned[t] = veggie;
if (veggie instanceof Potato)
bagged[t] = Potato.can(veggie);
else if (veggie instanceof Tomato)
bagged[t] = Tomato.can(veggie);
t++;
}
}
for (int i = 0; i < canned.length; i++) {
veggieChange(canned[i], bagged[i]);
}
}
It fixes the concurrency errors.
I'm still unsure if my approach is correct or not. So even though the question is mostly answered, opinions are still VERY welcome.
I'm POSITIVE that my title for this topic is not appropriate. Let me explain. The purpose of this is to duplicate a "Profile" application, where I have a profile and so would you. We both have our own followers and in this example, we both follow each other. What this method is needed to return is a cross reference based on whom you follow that I do not. I need this method to return to me a recommended Profile object that I do not already have in my array. Right now I'm having a difficult time with one line of code within a particular method.
One of my classes is a Set class that implements a SetInterface (provided by my professor) and also my Profile class that implements a ProfileInterface which was also provided. In my code for the Profile class, I have the following object: private Set<ProfileInterface> followBag = new Set<ProfileInterface>(); which utilizes the Array bag methods from my Set class with the ProfileInterface methods I've made.
Here is the method (not complete but can't move further without my problem being explained):
public ProfileInterface recommend(){
Set<ProfileInterface> recommended;
ProfileInterface thisProfile = new Profile();
for(int index = 0; index < followBag.getCurrentSize(); index++){
Set<ProfileInterface> follows = followBag[index].toArray();
for(int followedFollowers = 0; followedFollowers < follows.getCurrentSize(); followedFollowers++) {
if()
//if Profile's do not match, set recommended == the Profile
}
}
return recommended;
}
The purpose of this method is to parse through an array (Profile as this example) and then take each of those sub-Profiles and do a similar action. The reason for this much like "Twitter", "Facebook", or "LinkedIn"; where each Profile has followers. This method is meant to look through the highest Profiles follows and see if those subProfiles have any followers that aren't being followed by the highest one. This method is then meant to return that Profile as a recommended one to be followed. This is my first dealing with Array Bag data structures, as well as with generics. Through "IntelliJ", I'm receiving errors with the line Set<ProfileInterface> follows = followBag[index].toArray();. Let me explain the reason for this line. What I'm trying to do is take "my" profile (in this example), and see who I'm following. For each followed profile (or followBag[index]) I wish to see if followBag[index][index] == followBag[index] and continue to parse the array to see if it matches. But, due to my confusion with generics and array bag data structures, I'm having major difficulties figuring this out.
I'd like to do the following:
//for all of my followers
//look at a particular followed profile
//look at all of that profile's followers
//if they match one of my followers, do nothing
//else
//if they don't match, recommend that profile
//return that profile or null
My problem is that I do not know how to appropriately create an object of a Profile type that will allow me to return this object
(in my method above, the line Set<ProfileInterface> follows = followBag[index].toArray();)
I'm trying to make an index of my Profile set to an object that can later be compared where my difficulties are. I'd really appreciate any insight into how this should be done.
Much appreciated for all help and Cheers!
When you do:
Set<ProfileInterface> follows = followBag[index].toArray();
you're trying to use Set as Array. But you can't.
Java will not allow, because Set and Array are different classes, and Set does not support [] syntax.
That is why you get error. For usefollowBag as Array you have to convert it:
ProfileInterface[] profileArray = followBag.toArray(new ProfileInterface[followBag.size()]);
for(int i=0; i<profileArray.length; i++){
ProfileInterface profile = profileArray[i];
//do what you would like to do with array item
}
I believe, in your case, you don't need assign Set object to generic Array at all. Because you can enumerate Set as is.
public class Profile {
private Set<ProfileInterface> followBag = new HashSet<Profile>();
...
public Set<ProfileInterface> recommended(){
Set<ProfileInterface> recommendSet = new HashSet<ProfileInterface>();
for(Profile follower : followBag){
for(Profile subfollower : follower.followBag){
if(!this.followBag.contains(subfollower)){
recommendSet.add(subfollower);
}
}
}
return recommendSet;
}
}
I also added possibility of returning list of recommended profiles, because there is may be several.
Uncertain how best to word the title, but here's the gist.
The goal is to retrieve all selected rows of a table and manipulate them. The problem I'm bumping into is that the RowSetIterator doesn't get populated the first time the method within my backing bean is invoked. It does get populated when invoked a second time.
How do I go about getting it to work properly on the first invocation?
Doubtless I'm not being perfectly clear, please let me know if you require any additional information. Here's a snippet of the bean method:
public String deleteSelectedQueries()
{
JSFUtils.addInformationMessage("Delete");
RowKeySet selectedQueries =
getSavedQueriesByUserTable().getSelectedRowKeys();
Iterator selectedQueriesIter = selectedQueries.iterator();
DCBindingContainer bindings =
(DCBindingContainer) BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding savedQueriesByUserIter =
bindings.findIteratorBinding("SavedQueriesByUserROVOIterator");
RowSetIterator savedQueriesByUserRowSetIterator =
savedQueriesByUserIter.getRowSetIterator();
while (selectedQueriesIter.hasNext())
{
Key key = (Key) ((List) selectedQueriesIter.next()).get(0);
Row currentRow = savedQueriesByUserRowSetIterator.getRow(key);
System.out.println(currentRow.getAttribute("QueryName"));
}
return null;
}
}
Any ideas?
Thanks!
This code looks good to me.
The problem may come from <af:table> tag, make sure you have these tags removed:
selectedRowKeys="#{bindings.SavedQueriesByUserROVO.collectionModel.selectedRow}"
selectionListener="#{bindings.SavedQueriesByUserROVO.collectionModel.makeCurrent}"
I have a Table whose DataSource is set to a IndexedContainer. I also have multiple selection enabled on my Table. The Question is, how do I get all the selected values.. as an array perhaps?
My IndexedContainer:
private void populateAnalyteTable () {
Analyte[] analytes = Analyte.getAnalytes();
for (Analyte analyte : analytes) {
Object id = ic_analytes.addItem();
ic_analytes.getContainerProperty(id, "ID").setValue(analyte.getId());
ic_analytes.getContainerProperty(id, "Analyte Name").setValue(analyte.getAnalyteName());
}
// Bind indexed container to table
tbl_analytes.setContainerDataSource(ic_analytes);
}
What I'm eventually trying to get is an array of Analyte objects
Why do you want to use IndexContainer? Why don't you use BeanItemCotainer?
Please find the snippet of code below
table.setMultiSelect(true);
BeanItemContainer<Analyte> container = new BeanItemContainer<Analyte>(Analyte.class);
container.addAll(Arrays.asList(Analyte.getAnalytes()));
table.setContainerDatasource(container);
// Add some Properties of Analyte class that you want to be shown to user
table.setVisibleColumns(new Object[]{"ID","Analyte Name"});
//User selects Multiple Values, mind you this is an Unmodifiable Collection
Set<Analyte> selectedValues = (Set<Analyte>)table.getValue();
Please let me know in case it doesn't solve the issue
The vaadin objects supporting MultiSelect all return a set of the selected items.
https://www.vaadin.com/api/com/vaadin/ui/AbstractSelect.html#getValue%28%29
The drawback of this, if you need the selected items in "real" order (as displayed onscreen)
you will then have to find them from the Set to the Container
Just add your object as the Item-ID, like luuksen already propesed. Just change the initialisation of yout IndexedContainer to:
for (Analyte analyte : analytes) {
Object id = ic_analytes.addItem(analyte);
ic_analytes.getContainerProperty(id, "ID").setValue(analyte.getId());
ic_analytes.getContainerProperty(id, "Analyte Name").setValue(analyte.getAnalyteName());
}
table.getValue() is what you are looking for.
This method gives you an Object (if table is single select) or a Set<Object> (if multiselect) of the ID(s) of selected item(s). Runtime type depends on runtime id type, but if you do not need the value you can go around with Object .
If you are looking for Analytes as an array you can do
#SuppressWarnings("unchecked")
Set<Object> selectedIds = (Set<Object>) tbl_analytes.getValue();
List<Analyte> listAnalytes = new ArrayList<Analyte>();
for (Object id : selectedIds) {
listAnalytes.get(tbl_analytes.getItem(id));
}
listAnalytes.toArray();
Note that this approach works with every standard container you may use in Vaadin.
Regards!
EDIT: actually what .getValue() returns depends on the used container. In most of the cases it's the ID.
I have used linked lists before with Strings, doubles, etc., and they always worked exactly as expected. But now I am forming a linked list of items, and whenever I add a new element to the list, all objects in the list apparently become equal to the last object.
The essential code is as below:
import java.util.*;
public class Global
{
static public LinkedList<StockInfo> DiaryStocks = new LinkedList<StockInfo>();
static public class StockInfo //info related to each stock in diary
{
String recordDate;
String ticker;
int status;
String buyDate;
String sellDate;
double buyPrice;
double sellPrice;
double nmbrShares;
}//StockInfo
//The following function places the Diary data for a stock in the arraylist
static public void AddDiaryData(StockInfo thisdata)
{
String tckr;
int i;
DiaryStocks.add(thisdata);
for (i = 0; i < DiaryStocks.size(); i++) //this is debug code
{
tckr = DiaryStocks.get(i).ticker;
}
}
}
As I said, when single stepping through the debug code near the bottom, each time I add a new item to the list, the list size grows as it should, but the tckr item only corresponds to the last item added.
Any insights into this puzzle would be greatly appreciated.
John Doner
The problem is outside the code your provide. It is most likely that you are adding the same instance of StockInfo. Perhaps you have something like:
StockInfo info = new StockInfo();
for (...) {
info.setFoo(..);
info.setBar(..);
AddDiaryData(info);
}
You should not reuse instances like that. You should create a new instance each time.
As a sidenote - method names in Java should start with lowercase letter.
From the symptoms you are describing, it seems as if you are always adding a reference to the same StockInfo object instance to your list, rather than a reference to a new copy each time.
When that object is updated with the contents of the new entry, all list entries appear to change to reflect that latest entry.
This problem lies outside the code snippet that you posted, perhaps in the caller of the AddDiaryData method.
Ooops.
Deep Copy please search it
DiaryStocks.add(thisdata);
you should create new StockInfo() then add to the list otherwise you add the reference and it equalize all the reference of items to the last one