-
1. Re: a4j:support in t:dataTable / t:columns
nbelaevski Feb 13, 2009 8:36 PM (in response to nille)Hi Nils,
Code seems to be ok. QA team will check the problem in a next few days. -
2. Re: a4j:support in t:dataTable / t:columns
nille Feb 15, 2009 4:46 AM (in response to nille)Hi,
sorry, I forgot to mention that the 't'-Tags are Tomahawk tags.
Regards,
nille -
3. Re: a4j:support in t:dataTable / t:columns
tkuprevich Feb 16, 2009 6:39 AM (in response to nille)Hi, could you please upload your backing bean code, WorkloadBean? Thanks!
-
4. Re: a4j:support in t:dataTable / t:columns
nille Feb 20, 2009 10:29 AM (in response to nille)Hi,
sorry that I'm answering that late.
So, this is the backing bean code (quite a lot).
This is the code of the abstract bean the backing bean extends...public abstract class AbstractTableDisplayingBean { protected DataModel mColumns; protected DataModel mWorkloadDataModel; protected Map<Integer, Double > mValueMap = new HashMap<Integer, Double >(); protected int monthsToShow = 3; protected Date calendarStart; protected abstract Double getColumnValue(); protected abstract void fillRows(); protected abstract void fillColumns(); /* This method returns the columns of the model, * e.g.: KW1, KW2, KW3,... */ public DataModel getColumnDataModel() { return mColumns; } /* This method return the rows of the model, * e.g. Project P, Project D,... */ public DataModel getWorkloadDataModel() { return mWorkloadDataModel; } }
and this from the backing bean** * This bean is used to display an overview using the CalendarBean * and a list of the users TimeIntervals. * */ public class EmployeeCalendarWorkloadBean extends AbstractTableDisplayingBean { private String selectedProjectName = "initial"; private TimeInterval selectedTimeInterval = null; private List<List<String>> listWithRows; private List<String> listWithColumns; private static final int FILTER_ALL_CUSTOMERS = -1; private LoginController loginController; private List<CalendarItem> calItems; private List<TimeInterval> tIntervals; private List<SelectItem> customerFilterList = new ArrayList<SelectItem>(); private ArrayList<Integer> selectedCustomerFilterListItem = new ArrayList<Integer>(); private EntityManager entityManager; private EntityManagerFactory emf; private int sumTableRows = 1; private boolean alreadySet = false; private String employeeId; private String imitatingEmployeeId; private String sortColumn = null; private boolean sortAscending = true; DecimalFormat df = new DecimalFormat( "0.00" ); SimpleDateFormat sdf_year = new SimpleDateFormat(); /** * The constructor of the EmployeeCalendarWorkloadBean */ public EmployeeCalendarWorkloadBean() { /* This is used later for calendar calculations */ sdf_year.applyPattern("yyyy"); /* Set filter to display all projects/customers */ selectedCustomerFilterListItem.add(FILTER_ALL_CUSTOMERS); init(); } /** * The init method of the EmployeeCalendarWorkloadBean. This method * fills the rows and columns with data, which can be displayed on a JSp. * Rows hold CalendarItems (from a CalendarBean), columns hold projects. */ private void init() { log.debug(this.getClass().getName() + "init"); Map<String, Object> map = FacesContext.getCurrentInstance() .getExternalContext().getSessionMap(); if (map != null) { loginController = (LoginController) map.get("LoginBean"); if (loginController != null) { checkForChangedEmployeeIds(); if(alreadySet == false) { //calBean = new CalendarBean(); calBean.goToday(); } /* * If ColumnModel is empty, fill with CalendarItems (KW1, * KW2,...) */ if (mColumns == null) { fillColumns(); } /* if mWorkloadDataModel is empty, fill with */ if (mWorkloadDataModel == null) { fillRows(); } } } } /** * This method does the actual check for the current employee. If a manager has logged on, * he can impersonate a 'normal' employee. To actually see the employees TimeIntervals etc. * the init method must be called again. The need for this is checked here. */ private void checkForChangedEmployeeIds() { /* Check here if current employeeId is unequal than the * employeeId set in the LoginController. This can only happen if * current Employee is TeamLeader of employee identified by employeeId */ imitatingEmployeeId = loginController.getImitatingEmployeeId(); if( (imitatingEmployeeId != null) && (imitatingEmployeeId.equals(loginController.getEmployeeId()) == true)) { /* We are who we are: We are not imitating a different user (which _is_ allowed * to Manager [-> TeamLeader, GroupLeader] ) */ employeeId = imitatingEmployeeId; }else if( (imitatingEmployeeId != null) && (imitatingEmployeeId.equals(loginController.getEmployeeId()) == false) ) { /* We are acting as a different user*/ employeeId = imitatingEmployeeId; }else { /* No employeeId is set. We assume that we are acting as ourselves */ employeeId = loginController.getEmployeeId(); } } /** * Although this is a 'getter' this method does more than just * return a value. Depending on the current row and column this methd calculates * the average amount of hours. This is done by getting all TimeIntervals belonging * to the project, calculating the number of week of the current TimeInterval and * finally calculate the average afforded hours. * * @TODO Change the for-loop from all TimeIntevals to the one of the project (row)! Than the if-statement is not needed, too. * @return String - the average number of afforded hours for the project and calendar week */ /* This model returns the acutal values */ public Double getColumnValue() { /* We need this employee to get the FTE used to calculate the amount * of hours for team wide TimeIntervals */ emf = (EntityManagerFactory)ServiceFinder.findBean("entityManagerFactory"); entityManager = emf.createEntityManager(); Employee tmpEmployee = Employee.getEmployeeByEmpId(entityManager, employeeId); if(entityManager.isOpen() == true) { entityManager.close(); } DataModel wloadDataModel = getWorkloadDataModel(); if (wloadDataModel.isRowAvailable()) { Project row = (Project) wloadDataModel.getRowData(); DataModel columnDataModel = getColumnDataModel(); if (columnDataModel.isRowAvailable()) { CalendarItem column = (CalendarItem)columnDataModel.getRowData(); /* get correct value from TimeInterval, meaning * hours in calendar week = timeInterval.affordedHours / (timeInterval.untilWeekOfYear - timeInterval.untilWeekOfYear) * * For this we step through the timeInterval until we get a match * for a column (calendarWeek) within the timeInterval * */ /** * TODO Change the for-loop! Is it necessary to loop through ALL TimeIntevals? * Or is it sufficient to loop through all TimeIntervals belonging to the * project (row) * TODO Can this be done? org.hibernate.LazyInitializationException happens because * session is already closed and we use LAZY fetching! See TeamViewBean Javadoc for more info */ double summedUpResult = 0; log.info("\t\t*** Now KW: " + column.getCalendarWeek() + " / " + column.getCalendarYear() + "***"); for(TimeInterval ti : tIntervals) { /* This is for debug only */ if(log.isDebugEnabled()) { debugGetColumn(ti, row, column); } if(ti.getProject().getId() == row.getId()) { /* Used to calculate the hours per calendar week */ int ti_amount_of_cw = 0; double result = 0; /* We must check if the calendar reaches over a year break. * If that's the case, we split the calendar week in calendar weeks * before new year and after new year */ /* get number of weeks*/ ti_amount_of_cw = CalendarOperations.calculateNumOfWeeks(ti.getFrom(), ti.getUntil()); if(ti.getEntireTeam().equalsIgnoreCase("TRUE")) { result = ( (double)((ti.getAffordedHours() / ti_amount_of_cw ) ) ) * tmpEmployee.getOmegaFte(); }else{ result = (double)((ti.getAffordedHours() / ti_amount_of_cw ) ); } GregorianCalendar gc_from = CalendarOperations.calculateDateForFirstDayOfWeek(ti.getFrom()); gc_from.setFirstDayOfWeek(GregorianCalendar.MONDAY); GregorianCalendar gc_until = CalendarOperations.calculateDateForLastDayOfWeek(ti.getUntil()); gc_until.setFirstDayOfWeek(GregorianCalendar.MONDAY); GregorianCalendar gccolumn = CalendarOperations.calculateDateForFirstDayOfWeek(column.getCalendarDate()); gccolumn.setFirstDayOfWeek(GregorianCalendar.MONDAY); log.info("\t\t*** " + gc_from.getTime().toString() + " < " + gccolumn.getTime().toString() + " < " + gc_until.getTime().toString()); if( (gccolumn.before(gc_from)) || (gccolumn.after(gc_until)) ) { continue; }else{ // System.out.println("MATCH"); if(mValueMap.containsKey(column.getCalendarWeek())) { mValueMap.put(column.getCalendarWeek(), result + (Double)mValueMap.get(column.getCalendarWeek())); }else{ mValueMap.put(column.getCalendarWeek(), result); } /* Here we just sum up all proper results. Meaning all results belonging * to the one ProjectID. Because it may happen, that there multiple TimeIntervals entries * for one project in one and the same calendar week. */ if(result > 0) summedUpResult += result; } } } /* After iterating through all TimeIntervals we have the summed up * average hours for that one calendar week (column) and project (row) * and return it if > 0 else we return '-' at the end if the method */ if(summedUpResult > 0){ return roundToTwoDecimals(summedUpResult); } }else{ log.debug("Column with index : " + columnDataModel.getRowIndex() + " is not available"); } } return 0.0; } /** This method just returns values calculated before in method 'getColumnValue'. * That means, that method 'getColumnValue' has to be called before! * @return - String the sum of the average afforded hours of all projects in this calendar week * */ public Double getColumnSum() { DataModel columnDataModel = getColumnDataModel(); if (columnDataModel.isRowAvailable()) { CalendarItem column = (CalendarItem)columnDataModel.getRowData(); /** * TODO specify the match more precisely: calendarWeek and Year */ if(mValueMap.containsKey(column.getCalendarWeek())) { return roundToTwoDecimals((Double)mValueMap.get(column.getCalendarWeek())); } } return 0.0; } /** * This method just fills the columns with calendar items provided by the CalendarBean */ protected final void fillColumns() { calItems = calBean.getCalendarItems(); mColumns = new ListDataModel(calItems); } /** * This method fills the rows with projects which fit in the time span of the calendar items (columns) * provided by the CalendarBean. This method checks if the TimeInterval of a project is before or after the time span * and continues in this case. Otherwise the TimeInterval of the project is added to the rows. */ protected final void fillRows() { emf = (EntityManagerFactory)ServiceFinder.findBean("entityManagerFactory"); entityManager = emf.createEntityManager(); Employee tmpEmployee = Employee.getEmployeeByEmpId(entityManager, employeeId); List<Project> tmpList = new ArrayList<Project>(); tIntervals = new ArrayList<TimeInterval>(); tIntervals.addAll(tmpEmployee.getTimeIntervalList()); /* Now add TeamItems (time recording entries belonging to the entire team) * from the superior (DL or TeamLeader)*/ /* Now we have to add the items from the DL or TeamLeader. Items that do belong to the entire Team, * e.g X-mas, company holidays, etc * For that we first try to find the appropriate superior (DL or TeamLeader) of the current employee */ List<DeliveryLead> dLList = DeliveryLead.getAllDeliveryLeads(entityManager); for(DeliveryLead dl : dLList) { if(dl.hasTeamMember(entityManager, employeeId) == true) { tIntervals.addAll(dl.getTeamTimeIntervals()); } } dLList = null; List<TeamLeader> teamLeaderList = TeamLeader.getAllTeamLeader(entityManager); for(TeamLeader tl : teamLeaderList) { if(tl.hasTeamMember(entityManager, employeeId) == true) { tIntervals.addAll(tl.getTeamTimeIntervals()); } } teamLeaderList = null; customerFilterList.clear(); for(TimeInterval t: tIntervals) { if(log.isDebugEnabled()) { debugFillRows(t); } /* Just check the calendar objects. Are they in the same time span or are the overlapping? If no: just continue*/ GregorianCalendar gc_from = CalendarOperations.calculateDateForFirstDayOfWeek(t.getFrom()); //System.out.println("For date from : " + ti.getFrom() + " we calculated starting date: " + gc_from.getTime()); GregorianCalendar gc_until = CalendarOperations.calculateDateForLastDayOfWeek(t.getUntil()); //System.out.println("For date until : " + ti.getUntil() + " we calculated starting date: " + gc_until.getTime()); GregorianCalendar gc_calBeanstart = CalendarOperations.calculateDateForFirstDayOfWeek(calBean.getCalendarItems().get(0).getCalendarDate()); GregorianCalendar gc_calBeanend = CalendarOperations.calculateDateForFirstDayOfWeek(calBean.getCalendarItems().get(calBean.getCalendarItems().size()-1).getCalendarDate()); if( (gc_until.before(gc_calBeanstart)) || (gc_from.after(gc_calBeanend)) ) { continue; } /* We have to check if the project is already in the list. * This can happen because there can be more than one TimeInterval * for e project * */ if(tmpList.contains(t.getProject()) == false) { /* and we check if the filter is set to ALL or to the specific customer */ //if( ( selectedCustomerFilterListItem.contains(new Integer(FILTER_ALL_CUSTOMERS))) || if( ( selectedCustomerFilterListItem.contains(Integer.valueOf(FILTER_ALL_CUSTOMERS))) || ( selectedCustomerFilterListItem.contains( //new Integer(t.getProject().getCounterparty().getId()) Integer.valueOf(t.getProject().getCounterparty().getId()) ) == true) ) { tmpList.add(t.getProject()); } }else{ log.debug("Project: " + t.getProject().toString() + " with T-ID: " + t.getId() + " is already in list for rows!"); } /* To prevent duplicates in the filter list, we check the existing list first */ if(customerFilterListContains(t.getProject().getCounterparty().getId()) == false ) { customerFilterList.add(new SelectItem(t.getProject().getCounterparty().getId(),t.getProject().getCounterparty().getName())); log.debug("PUT: " + t.getProject().getCounterparty().getName() + " into customerList"); } } mWorkloadDataModel = new ListDataModel(tmpList); if(entityManager.isOpen()) { log.debug("EmployeeCalendarWorkloadBean closing em..."); entityManager.close(); } } /** * This method is used to filter the rows. The list of selected customers * is filled via the getter but we need this method to apply the filter * because scope is request scope */ public void setCustomerFilter() { log.debug(this.getClass().getName() + "changeCustomerFilter"); log.debug("SelectedCustomer is: " + selectedCustomerFilterListItem); if(monthsToShow != calBean.getMonthsToShow()) { calBean.setMonthsToShow(monthsToShow); calBean.repopulatCalendarItemsList(); } Calendar cal = Calendar.getInstance(); cal.setTime(calendarStart); calBean.setCurrentFirstDayOfMonth(cal); calBean.repopulatCalendarItemsList(); fillColumns(); fillRows(); } /** * This is just a helper method to check if an Customer is already * in a list. Used by the customer filter. * @param customerID - ID of a customer * @return boolean- - true if customer is already in list, ohterwise false */ private boolean customerFilterListContains(int customerID) { for(int i = 0; i<customerFilterList.size();i++) { SelectItem tmpSI = customerFilterList.get(i); Integer tmpSI_ID = (Integer)tmpSI.getValue(); if(tmpSI_ID.intValue() == customerID) { return true; } } return false; } /** * This method has to be used to validate the list box for the customer filter. Because * the same HTML/JSP web site is loaded again after changing the customer in the filter list box * the originally entries within the list box are not longer valid. Without this method the JSF-engine * states an validation exception and displays the site before choosing a value of the list box. by using this * method, we update the columns and rows and by doing this also the content of the list box (in the method fillRows). * No validation exception happens because the originally content of the list box is no longer used. * @param context - the FacesContext * @param toValidate - the component which should be validated * @param value - the value transmitted from the component, here customer ID */ public void validateSelectBox(FacesContext context, UIComponent toValidate, Object value) { fillColumns(); fillRows(); if(log.isDebugEnabled()) { debugValidateSelectBox((Object[])value); } ((UIInput)toValidate).setValid(true); } /*--------------------------------*/ /* Setter and getter do come here */ /*--------------------------------*/ public LoginController getLoginController() { return loginController; } public void setLoginController(LoginController loginController) { this.loginController = loginController; } /*....*/ public void doit() { System.out.println("In doit"); System.out.println("in calculateprojectDetails: "); DataModel wloadDataModel = getWorkloadDataModel(); if (wloadDataModel.isRowAvailable()) { System.out.println("in calculateprojectDetails: rowAvailable"); Project row = (Project) wloadDataModel.getRowData(); DataModel columnDataModel = getColumnDataModel(); if (columnDataModel.isRowAvailable()) { System.out.println("in calculateprojectDetails: columnAvailable"); CalendarItem column = (CalendarItem)columnDataModel.getRowData(); selectedProjectName = "! " + row.getName() + " :: " + column.getCalendarWeek() + " OLD: " + selectedProjectName; System.out.println("in calculateprojectDetails: " + selectedProjectName); for(TimeInterval ti : tIntervals) { GregorianCalendar gc_from = CalendarOperations.calculateDateForFirstDayOfWeek(ti.getFrom()); gc_from.setFirstDayOfWeek(GregorianCalendar.MONDAY); GregorianCalendar gc_until = CalendarOperations.calculateDateForLastDayOfWeek(ti.getUntil()); gc_until.setFirstDayOfWeek(GregorianCalendar.MONDAY); GregorianCalendar gccolumn = CalendarOperations.calculateDateForFirstDayOfWeek(column.getCalendarDate()); gccolumn.setFirstDayOfWeek(GregorianCalendar.MONDAY); if(ti.getProject().getId() == row.getId()){ if( (gccolumn.before(gc_from)) || (gccolumn.after(gc_until)) ) { continue; }else{ selectedTimeInterval = ti; } } } } } } }
-
5. Re: a4j:support in t:dataTable / t:columns
adubovsky Feb 24, 2009 9:15 AM (in response to nille)Hello nille,
I have reproduced your problem. A4j:support with ajaxSingle=true inside t:columns does not call action and actionListener. And this is problem in tomahawk colums. You could use rich:columns instead of t:columns and all will be OK. -
6. Re: a4j:support in t:dataTable / t:columns
nille Mar 4, 2009 2:09 AM (in response to nille)Hi adubovsky,
thanks for your effort. I decided to switch to richfaces datatable (and eliminate Tomahawk where possible) to prevent further irritations using two frameworks.
Thanks a lot and kind regards,
Nille