diff --git a/serverApps/build.xml b/serverApps/build.xml index 8f431843a3..61faf62aa5 100644 --- a/serverApps/build.xml +++ b/serverApps/build.xml @@ -8,158 +8,84 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -227,8 +153,8 @@ - - + + diff --git a/serverApps/src/main/servlet/org/compiere/jsf/AdempiereServlet.java b/serverApps/src/main/servlet/org/compiere/jsf/AdempiereServlet.java new file mode 100755 index 0000000000..613b269d47 --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/AdempiereServlet.java @@ -0,0 +1,106 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import java.io.IOException; +import java.util.Properties; +import java.util.logging.Level; +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.UnavailableException; + +import org.compiere.Adempiere; +import org.compiere.util.CLogMgt; +import org.compiere.util.CLogger; +import org.compiere.util.Env; +import org.compiere.util.Ini; +import org.compiere.util.Login; + +/** + * for this project, this servlet needs to be replaced by a backing bean that can also log out + * initializes the adempiere "engine" -- basically logs into the server + * web.xml snippet: + * + adempiereInitServlet + org.compiere.jsf.AdempiereInitServlet + 1 + + * @author rfreden + * @todo wouldn't it be cool to have a Filter to implement lazy loading? + * @fixme the adempiere code here does a System.exit (terminating tomcat...) if it fails to connect to the db + */ +public class AdempiereServlet implements Servlet +{ + private static final CLogger log=CLogger.getCLogger(AdempiereServlet.class); + + private Properties adempiereProperties; + + private ServletConfig servletConfig=null; + + /** + * nop method, because this servlet doesn't actually serve anything + */ + public void service(ServletRequest servletRequest,ServletResponse servletResponse) + throws ServletException, IOException + {} + + public void init(ServletConfig s) throws ServletException + { + servletConfig=s; + // Adempiere start up and properties setup + //org.compiere.Adempiere.startupEnvironment(true); + if(!Adempiere.startupEnvironment(true)) + throw new UnavailableException("adempiere init failed"); + adempiereProperties = Env.getCtx(); + //CLogMgt.setLoggerLevel(Level.FINE, null); + CLogMgt.setLevel(Level.ALL); + + Ini.setProperty(Ini.P_UID, "SuperUser"); + Ini.setProperty(Ini.P_PWD, "System"); + Ini.setProperty(Ini.P_ROLE, "GardenWorld Admin"); + Ini.setProperty(Ini.P_CLIENT, "GardenWorld"); + Ini.setProperty(Ini.P_ORG, "*"); + Ini.setProperty(Ini.P_LANGUAGE, "English"); + //Ini.setProperty(Ini.P_LANGUAGE, "Danish_dk_DK"); + Ini.setProperty(Ini.P_WAREHOUSE, ""); + Login login = new Login(adempiereProperties); + + if (!login.batchLogin(null)) + throw new UnavailableException("Adempiere login failed"); + + log.info("adempiere login complete"); + } + + public String getServletInfo() + { + return "Adempiere Initialization Servlet"; + } + + public ServletConfig getServletConfig() + { + return servletConfig; + } + + /** + * @todo implement this method + */ + public void destroy() + {} +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerLookup.java b/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerLookup.java new file mode 100755 index 0000000000..c19510da6d --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerLookup.java @@ -0,0 +1,222 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import java.util.HashMap; + +import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; + +import org.compiere.model.GridTab; +import org.compiere.model.GridWindow; +import org.compiere.util.CLogger; + +/** + * this class does the actual work for variables that start with actionListener_lookup + * basically every method here should have a void return type and take an ActionEvent as argument + * TODO: implement all methods for the dropdown and button menus, list them here + * gridToggle + * + * @author rfreden + * + */ +public class DynamicActionListenerLookup +{ + // this class makes use of the hidden variable "tabNo" + // which contains tab0Grid or somesuch, identifying the panel that's currently on top + // where the digit in the middle is the tabNo for compiere + + // in case it will matter, it will also have a windowNo, a unique window identifier for compiere + private static final CLogger log=CLogger.getCLogger(DynamicActionListenerLookup.class); + + private FacesContext facesContext; + + private Long tabNo; + + private TabStateManager tabStateManager; + + public DynamicActionListenerLookup(FacesContext ctx) + { + facesContext=ctx; + tabStateManager=new TabStateManager(facesContext); + } + + // FIXME: implement all these method stubs + public void undo(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void help(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void createNew(ActionEvent ae) + { + throw new UnsupportedOperationException(); + + } + + public void delete(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + /** + * tab control actionListener method; use actionListener="actionListener_lookup.focus" + * to raise the tab described by currentTabNo + * @param ae + */ + public void focus(ActionEvent ae) + { + log.info("focusing on tabNo "+tabNo); + tabStateManager.getUIState().setTabNo(tabNo.intValue()); + } + + public void save(ActionEvent ae) + { + // save tab on window + // check if this is called during the + GridTab gridTab=getCurrentGridTab(); + gridTab.getTableModel().open(0); + log.info("saving tab "+gridTab.getTabNo()); + if(!gridTab.dataSave(true)) + log.info("failed to save tab"); + } + + public void refresh(ActionEvent ae) + { + log.info("called"); + // FIXME: this open method is hackish at best + getCurrentGridTab().getTableModel().open(0); + getCurrentGridTab().dataRefresh(); + } + + public void lookup(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void attachment(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } +/* + public void gridToggle(ActionEvent ae) + { + log.info("entered"); + tabStateManager.gridToggle(); + } +*/ + public void history(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void menu(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void parent(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void detail(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void first(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void previous(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void next(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void last(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void report(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void archived(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void print(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void zoom(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void active(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void check(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void product(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void exit(ActionEvent ae) + { + throw new UnsupportedOperationException(); + } + + public void setTabNo(Long l) + { + log.info("setting tabNo to "+l); + tabNo=l; + } + + // these three parse the tabNo string + // FIXME: check them + private GridTab getCurrentGridTab() + { + Integer key=new Integer(tabStateManager.getUIState().getWindowNo()); + // get window from hashmap "grids" + GridWindow gridWindow=((HashMap)facesContext.getExternalContext() + .getSessionMap().get("grids")).get(key); + return gridWindow.getTab(tabStateManager.getUIState().getTabNo().intValue()); + } +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerPropertyResolver.java b/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerPropertyResolver.java new file mode 100755 index 0000000000..8546b22aea --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerPropertyResolver.java @@ -0,0 +1,116 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import javax.faces.el.PropertyNotFoundException; +import javax.faces.el.PropertyResolver; +import org.compiere.util.CLogger; + +/** + * this class continues the el lookup initiated by DynamicActionListenerVariableResolver, + * resolving the value to the proper name + * hmmm, i think this whole class is unnecessary + */ +public class DynamicActionListenerPropertyResolver extends PropertyResolver +{ + private final static CLogger log=CLogger.getCLogger(DynamicActionListenerPropertyResolver.class); + + private PropertyResolver originalResolver; + + public DynamicActionListenerPropertyResolver(PropertyResolver propertyResolver) + { + //log.info("entered"); + originalResolver = propertyResolver; + } + + public Object getValue(Object base,Object property) throws PropertyNotFoundException + { + if (base instanceof DynamicActionListenerLookup) + { + if(property instanceof Long) + ((DynamicActionListenerLookup)base).setTabNo((Long)property); + return base; + //throw new PropertyNotFoundException(); + } + return originalResolver.getValue(base,property); + } + + public Object getValue(Object base,int index) throws PropertyNotFoundException + { + if(base instanceof DynamicActionListenerLookup) + throw new PropertyNotFoundException(); + return originalResolver.getValue(base,index); + } + + /** + * TODO: test this method + */ + public void setValue(Object base,Object property,Object value) throws PropertyNotFoundException + { + //log.info("entered"); + if(base instanceof DynamicActionListenerLookup) + throw new PropertyNotFoundException("attempted to call set on a read-only field"); + else + { + originalResolver.setValue(base,property,value); + } + } + + public void setValue(Object obj,int i,Object obj1) throws PropertyNotFoundException + { + //log.info("entered"); + if(obj instanceof DynamicActionListenerLookup) + throw new PropertyNotFoundException(); + else + originalResolver.setValue(obj,i,obj1); + } + + public boolean isReadOnly(Object base,Object property) throws PropertyNotFoundException + { + //log.info("entered"); + if(base instanceof DynamicActionListenerLookup) + throw new PropertyNotFoundException(); + return originalResolver.isReadOnly(base,property); + } + + public boolean isReadOnly(Object obj,int i) throws PropertyNotFoundException + { + //log.info("entered"); + if(obj instanceof DynamicActionListenerLookup) + throw new PropertyNotFoundException(); + return originalResolver.isReadOnly(obj,i); + } + + // this should probably throw for our object + public Class getType(Object obj,Object obj1) throws PropertyNotFoundException + { + //log.info("entered"); + //if (!(obj instanceof DynamicFieldLookup)) + // hope this works.. + return originalResolver.getType(obj,obj1); + //else + // return com.ibm.faces.databind.SelectItemsWrapper.class; + } + + public Class getType(Object obj,int i) throws PropertyNotFoundException + { + //log.info("entered"); + if(obj instanceof DynamicActionListenerLookup) + throw new PropertyNotFoundException(); + return originalResolver.getType(obj,i); + } +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerVariableResolver.java b/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerVariableResolver.java new file mode 100755 index 0000000000..ff5de30382 --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/DynamicActionListenerVariableResolver.java @@ -0,0 +1,49 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import javax.faces.context.FacesContext; +import javax.faces.el.VariableResolver; +import org.compiere.util.CLogger; + +/** + * this class exists only to signal that this is a custom lookup + */ +public class DynamicActionListenerVariableResolver extends VariableResolver +{ + private static final String LOOKUP_VAR="actionListener_lookup"; + private static final CLogger log=CLogger.getCLogger(DynamicActionListenerVariableResolver.class); + + private VariableResolver originalResolver; + + public DynamicActionListenerVariableResolver(VariableResolver variableResolver) + { + originalResolver=variableResolver; + } + + public Object resolveVariable(FacesContext facescontext, String s) + { + //log.info("resolving var "+s); + if(s.equals(LOOKUP_VAR)) + { + //log.info("matched a dynamic lookup for "+LOOKUP_VAR); + return new DynamicActionListenerLookup(facescontext); + } + //log.info("failed to match"); + return originalResolver.resolveVariable(facescontext,s); + } +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldLookup.java b/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldLookup.java new file mode 100755 index 0000000000..cbc41fc294 --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldLookup.java @@ -0,0 +1,333 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Level; + +import javax.faces.context.FacesContext; +import javax.faces.el.PropertyNotFoundException; +import javax.faces.model.SelectItem; + +import org.compiere.model.GridField; +import org.compiere.model.GridTab; +import org.compiere.model.GridWindow; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.compiere.util.NamePair; + +/** + * this class provides enough of an interface to compiere to get values for a + * field's label, tooltip text, and value from the compiere model + */ +public class DynamicFieldLookup +{ + private final static CLogger log=CLogger.getCLogger(DynamicFieldLookup.class); + + private FacesContext facesContext; + + private Long tabNumber; + + private String columnName; + + private GridTab gridTab; + + private TabStateManager tabStateManager; + + // this exists so we can always call .value in el + static public class FieldProxy + { + private GridField gridField; + + public FieldProxy(GridField gF) + { + gridField=gF; + } + + public Object getValue() + { + return convertToValue(); + } + + public String getLabel() + { + //log.info("returning label "+gridField.getHeader()); + if(gridField.getDisplayType()==28) + { + if (gridField.getColumnName().equals("PaymentRule")) + { + return readReference(195); + //this.setForeground(Color.blue); + //setIcon(Env.getImageIcon("Payment16.gif")); // 29*14 + } + else if (gridField.getColumnName().equals("DocAction")) + { + return readReference(135); + //this.setForeground(Color.blue); + //setIcon(Env.getImageIcon("Process16.gif")); // 16*16 + } + else if (gridField.getColumnName().equals("CreateFrom")) + { + //setIcon(Env.getImageIcon("Copy16.gif")); // 16*16 + } + else if (gridField.getColumnName().equals("Record_ID")) + { + //setIcon(Env.getImageIcon("Zoom16.gif")); // 16*16 + // FIXME: this probably does something that needs to be emulated in our jsf layer + //this.setText(Msg.getMsg(Env.getCtx(), "ZoomDocument")); + } + else if (gridField.getColumnName().equals("Posted")) + { + return readReference(234); + //this.setForeground(Color.magenta); + //setIcon(Env.getImageIcon("InfoAccount16.gif")); // 16*16 + } + } + return gridField.getHeader(); + } + + public String getTooltip() + { + return gridField.getDescription(); + } + + // arg may need to be an Object to handle all cases + public void setValue(Object o) + { + String s=o.toString(); + // some values may not be writable, should catch it in DynamicFieldPropertyResolver.isReadOnly + if(s.equals("true")) + s="Y"; + else if(s.equals("false")) + s="N"; + + // TODO: this really probably belongs somewhere else + + String ret=gridField.setValueValidate(s,true); + if(ret!=null) + throw new PropertyNotFoundException(ret); + //log.info("got back from setValueValidate (null is success) "+ret); + } + + // this is for conversion in jsf + public Class getType() + { + // TODO: there probably need to be other types here (Date in the future, for one) + if(gridField.getDisplayType()==20) + return java.lang.Boolean.class; + return java.lang.String.class; + } + + private Object convertToValue() + { + int displayType=gridField.getDisplayType(); + //log.info("got display type "+displayType); + // TODO: this only has like... 3 or 4 unique cases, refactor for + // reuse + // check display type to genereate jsf code for each specific + // component + switch (displayType) + { + case 10: + case 11: + case 12: + case 13: + case 14: + case 22: + case 29: + case 33: + case 34: + case 35: + case 36: + case 37: + // text box + // check if same line. make sure that it isn't the first field. + // It is possible that the first field can have same line checked and that would cause + // formatting issues. + log.info("getValue1 "+gridField.getValue()); + log.info("getValue2 "+gridField.getValue()); + return gridField.getValue(); + case 15: + // may want to convert this to a java.util.Date, same for case 16 + // date. have to chop timestamp off of gridField value + String dateString=""; + if(gridField.getValue()!=null) + { + String[] dateArray=gridField.getValue().toString().split(" "); + dateString=dateArray[0]; + return dateString; + } + case 16: + // probably unused so far + // date + time + // check if same line. make sure that it isn't the first field. + // It is possible that the first field can have same line checked and that + // would cause formatting issues. + return gridField.getValue(); + case 17: + case 18: + case 19: + // check if same line. make sure that it isn't the first field. + // It is possible that the first field can have same line checked and that would cause + // formatting issues. + ArrayList tmp=gridField.getLookup().getData(true, true, true, true); + ArrayList valueNamePairList=tmp; + ArrayList selectItems=new ArrayList(); + for(int i=0; i(); + String SQL; + if (Env.isBaseLanguage(Env.getCtx(), "AD_Ref_List")) + SQL = "SELECT Name FROM AD_Ref_List WHERE AD_Reference_ID=?"; + else + SQL = "SELECT t.Name FROM AD_Ref_List l, AD_Ref_List_Trl t " + + "WHERE l.AD_Ref_List_ID=t.AD_Ref_List_ID" + + " AND t.AD_Language='" + Env.getAD_Language(Env.getCtx()) + "'" + + " AND l.AD_Reference_ID=?"; + + try + { + PreparedStatement pstmt = DB.prepareStatement(SQL, null); + pstmt.setInt(1, AD_Reference_ID); + ResultSet rs = pstmt.executeQuery(); + rs.next(); + String name = rs.getString(1); + rs.close(); + pstmt.close(); + return name; + } + catch (SQLException e) + { + log.log(Level.SEVERE, SQL, e); + } + return "ERROR"; + } // readReference + } // end FieldProxy + + public DynamicFieldLookup(FacesContext ctx) + { + facesContext=ctx; + tabStateManager=new TabStateManager(facesContext); + } + + public FieldProxy getProxy() + { + return new FieldProxy(gridTab.getField(columnName)); + } + + /** + * sets the GridTab for this field + * @param l + */ + public void setTabNumber(Long l) + { + //log.info("setting tab number"); + tabNumber=l; + // window # is available as a hidden field named windowNo + // GridWindows are stored in a session Map called grid + HashMap grids=(HashMap)facesContext.getExternalContext().getSessionMap().get("grids"); + //log.info("grids is "+grids+" getting windowNo "+tabStateManager.getUIState().getWindowNo()); + GridWindow gridWindow=grids.get(new Integer(tabStateManager.getUIState().getWindowNo())); + //log.info("gridWindow is "+gridWindow); + gridTab=gridWindow.getTab((int)tabNumber.longValue()); + //log.info("gridTab open status "+gridTab.isOpen()); + } + + /** + * + */ + public void setColumnName(String s) + { + // error checking for testing in development, all of this but the final assignment can be commented out in release + boolean b=false; + GridField[] gridFields=gridTab.getFields(); + for(int i=0;i > getProxies() + { + GridField[] gridFields=gridTab.getFields(); + ArrayList fieldProxies=new ArrayList(); + log.info("got "+gridFields.length+" fields"); + for (int i=0;i > tmp=new ArrayList >(); + tmp.add(fieldProxies); + return tmp; + } +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldPropertyResolver.java b/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldPropertyResolver.java new file mode 100755 index 0000000000..1af55b6691 --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldPropertyResolver.java @@ -0,0 +1,172 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import javax.faces.el.PropertyNotFoundException; +import javax.faces.el.PropertyResolver; +import org.compiere.util.CLogger; + +/** + * this class continues the el lookup initiated by DynamicFieldVariableResolver, + * resolving the value to the proper name + * + * TODO: this should deduce the tab number from the hidden field id = "tabNo" + */ +public class DynamicFieldPropertyResolver extends PropertyResolver +{ + // yes these should probably be an enum + public static final String DYNAMIC_VALUE_TOKEN="value"; + public static final String DYNAMIC_LABEL_TOKEN="label"; + public static final String DYNAMIC_TOOLTIP_TOKEN="tooltip"; + public static final String DYNAMIC_COLLECTION_TOKEN="fields"; + // less related to the others, these are more application state than 1:1 with compiere model + //public static final String DYNAMIC_TAB_TOKEN="tabNo"; + //public static final String DYNAMIC_GRID_TOKEN="gridView"; + + private final static CLogger log=CLogger.getCLogger(DynamicFieldPropertyResolver.class); + + private PropertyResolver originalResolver; + + public DynamicFieldPropertyResolver(PropertyResolver propertyResolver) + { + originalResolver = propertyResolver; + } + + public Object getValue(Object o1,Object o2) throws PropertyNotFoundException + { + //log.info("entered getValue(Object,Object), base is type "+o1.getClass().getName()+" property is type "+o2.getClass().getName()+" value "+o2.toString()); + if (o1 instanceof DynamicFieldLookup) + { + //log.info("matches dynamic lookup"); + DynamicFieldLookup dynamicFieldLookup=(DynamicFieldLookup)o1; + if(o2 instanceof Long) + { + //log.info("looking up tab index "+(Long)o2); + dynamicFieldLookup.setTabNumber((Long)o2); + return dynamicFieldLookup; + } + else + { + //log.info("looking up named property "+(String)o2); + String s=(String)o2; + if(s.equals(DYNAMIC_VALUE_TOKEN)) + { + Object o=dynamicFieldLookup.getProxy().getValue(); + return o; + } + else if(s.equals(DYNAMIC_LABEL_TOKEN)) + return dynamicFieldLookup.getProxy().getLabel(); + else if(s.equals(DYNAMIC_TOOLTIP_TOKEN)) + return dynamicFieldLookup.getProxy().getTooltip(); + else if(s.equals(DYNAMIC_COLLECTION_TOKEN)) + return dynamicFieldLookup.getProxies(); + //else if(s.equals(DYNAMIC_TAB_TOKEN)) + // return dynamicFieldLookup.getTabNo(); + //else if(s.equals(DYNAMIC_GRID_TOKEN)) + // return dynamicFieldLookup.getGridView(); + else + { + dynamicFieldLookup.setColumnName(s); + return dynamicFieldLookup; + } + } + } + return originalResolver.getValue(o1,o2); + } + + public Object getValue(Object obj,int i) throws PropertyNotFoundException + { + if(obj instanceof DynamicFieldLookup) + throw new PropertyNotFoundException(); + return originalResolver.getValue(obj,i); + } + + /** + * TODO: test this method + */ + public void setValue(Object base,Object property,Object value) throws PropertyNotFoundException + { + if(base instanceof DynamicFieldLookup) + { + //log.info("setValue called for column "+((DynamicFieldLookup)base).getColumnName()+" value type "+value.getClass().getName()+" value "+value.toString()); + DynamicFieldLookup dfl=(DynamicFieldLookup)base; + String s=(String)property; + if(s.equals(DYNAMIC_VALUE_TOKEN)) // FIXME: this will probably break + { + dfl.getProxy().setValue(value.toString()); + } + else // tabNo fits this case + log.info("attempted to call set on read-only field: "+((DynamicFieldLookup)base).getColumnName()+" with terminating token "+s); + } + else + { + originalResolver.setValue(base,property,value); + } + } + + public void setValue(Object obj,int i,Object obj1) throws PropertyNotFoundException + { + if(obj instanceof DynamicFieldLookup) + { + //log.info("setValue with int arg called"); + throw new PropertyNotFoundException(); + } + else + originalResolver.setValue(obj,i,obj1); + } + + // FIXME: this likely needs to be a non constant return for custom lookup (false for value lookup?) + public boolean isReadOnly(Object base,Object property) throws PropertyNotFoundException + { + //log.info("invoked isReadOnly"); + if(base instanceof DynamicFieldLookup) + { + // FIXME: lookups obviously have more properties than just a name + // so we should associate them logically, java enums? or give them to different resolver classes perhaps + log.info("base id DynamicFieldLookup, property is "+property.toString()); + if(property instanceof String && ( ((String)property).equals("value") || ((String)property).equals("gridView") || ((String)property).equals("tabNo") )) + return false; + else + return true; + } + return originalResolver.isReadOnly(base,property); + } + + public boolean isReadOnly(Object obj,int i) throws PropertyNotFoundException + { + //log.info(""); + if(obj instanceof DynamicFieldLookup) + return true; + return originalResolver.isReadOnly(obj,i); + } + + public Class getType(Object base,Object property) throws PropertyNotFoundException + { + //log.info("getType called, base is of type "+base.getClass().getName()+" value "+base.toString()+" property is of type "+property.getClass().getName()+" value "+property.toString()+" and column name is "+((DynamicFieldLookup)base).getColumnName()); + // FIXME: this needs to return the type (to convert to from String) of the column + //return originalResolver.getType(base,property); + //return java.lang.String.class; + return ((DynamicFieldLookup)base).getProxy().getType(); + } + + public Class getType(Object obj,int i) throws PropertyNotFoundException + { + if(obj instanceof DynamicFieldLookup) + throw new PropertyNotFoundException(); + return originalResolver.getType(obj,i); + } +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldVariableResolver.java b/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldVariableResolver.java new file mode 100755 index 0000000000..9e162daa07 --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/DynamicFieldVariableResolver.java @@ -0,0 +1,51 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import javax.faces.context.FacesContext; +import javax.faces.el.VariableResolver; + +import org.compiere.util.CLogger; + +/** + * this class exists only to signal that this is a custom lookup + */ +public class DynamicFieldVariableResolver extends VariableResolver +{ + private static final CLogger log=CLogger.getCLogger(DynamicFieldVariableResolver.class); + + private static final String LOOKUP_VAR="tab_lookup"; + + private VariableResolver originalResolver; + + public DynamicFieldVariableResolver(VariableResolver variableResolver) + { + originalResolver=variableResolver; + } + + public Object resolveVariable(FacesContext facescontext, String s) + { + //log.info("resolving var "+s); + if(s.equals(LOOKUP_VAR)) + { + //log.info("matching tab_lookup"); + return new DynamicFieldLookup(facescontext); + } + //log.info("failed to match"); + return originalResolver.resolveVariable(facescontext,s); + } +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/JSFFilter.java b/serverApps/src/main/servlet/org/compiere/jsf/JSFFilter.java new file mode 100755 index 0000000000..8569814d6c --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/JSFFilter.java @@ -0,0 +1,934 @@ +/******************************************************************************* + * Product: Adempiere ERP & CRM Smart Business Solution * Copyright (C) 1999-2006 + * ComPiere, Inc. All Rights Reserved. * This program is free software; you can + * redistribute it and/or modify it * under the terms version 2 of the GNU + * General Public License as published * by the Free Software Foundation. This + * program is distributed in the hope * that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more + * details. * You should have received a copy of the GNU General Public License + * along * with this program; if not, write to the Free Software Foundation, + * Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * For the text + * or an alternative of this public license, you may reach us * ComPiere, Inc., + * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * or via + * info@compiere.org or http://www.compiere.org/license.html * + ******************************************************************************/ +package org.compiere.jsf; + +import java.io.*; +import java.sql.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import org.compiere.model.*; +import org.compiere.util.*; + +/** + * JSF Filter + * @author zbeatty + */ +public class JSFFilter implements Filter +{ + + private FilterConfig filterConfig = null; + + /** Logging */ + private static CLogger log = CLogger.getCLogger (JSFFilter.class); + + /** GridWindow timestamp */ + private long gridWindowTimestamp; + + /** Environment Variable */ + private Properties ctx; + + /** ID's and Window Nums */ + private int windowId; + + private int windowNo; + + /** Tab count */ + private int tabCount; + + /** GridWindow, GridTab, GridFields */ + private GridWindow gridWindow = null; + + private ArrayList tabList; + + /** + * Init + * @param config configuration + * @throws ServletException + */ + public void init(FilterConfig filterConfig) + throws ServletException + { + this.filterConfig = filterConfig; + ctx = Env.getCtx (); + } + + /** + * Destroy + */ + public void destroy() + { + this.filterConfig = null; + } + + /** + * The filter checks to see if the requested file already exists. If it + * doesn't exist, then it generates a new file for the page requested. If it + * does exist, it compares the timestamp on the file to the timestamp on the + * GridWindow object to make sure it is not out of date. If it is out of + * date, it generates a new file for the page requested. If it is not out of + * date, displays the existing, up to date file. + * @param ServletRequest request + * @param ServletResponse response + * @param FilterChain chain + * @throws IOException + * @throws ServletException + */ + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) + throws IOException, ServletException + { + // cast request into HttpServletRequest + HttpServletRequest httpServletRequest = (HttpServletRequest)request; + HttpSession session = null; + // get session from request. Using boolean true should create a new + // session if session doesn't exist + try + { + session = httpServletRequest.getSession (true); + } + catch (Exception e) + { + log + .warning ("There was a problem getting the session from the HttpServletRequest"); + } + // get windowNo and windowId out of the request + try + { + windowNo = (Integer.parseInt (httpServletRequest + .getParameter ("windowNo"))); + windowId = (Integer.parseInt (httpServletRequest + .getParameter ("windowId"))); + } + catch (NumberFormatException nfe) + { + log.info ("There was an error getting the request parameters: " + + nfe); + } + // holds HashMap(WindowNo, GridWindow) + HashMap grids = new HashMap (); + StringBuilder generatedJSF = new StringBuilder (); + // get context and path to store file + + // holds servlet context path + String realContextPath = session.getServletContext ().getRealPath ("/"); + try + { + // get "grids" out of the session to see if window exists + // note: attribute "grids" is expected to be in the session before + // the filter is hit. + if (session.getAttribute ("grids") != null) + { + grids = (HashMap)session + .getAttribute ("grids"); + } + // see if requested windowNo is in session + if (grids.isEmpty () || (!grids.containsKey (windowId))) + { + gridWindow = GridWindow.get (ctx, windowNo, windowId); + } + else + { + gridWindow = grids.get (windowNo); + } + String jsfFile = realContextPath + "window/" + + formatNameWithFirstLowerCase (gridWindow.getName ()) + ".jsp"; + File file = new File (jsfFile); + // check if file exists and up to date + if (file.exists ()) + { + gridWindowTimestamp = getGridWindowTimeStamp (); + if (gridWindowTimestamp > file.lastModified ()) + { + generateJSFPage (generatedJSF, realContextPath); + saveFile (file, generatedJSF.toString ()); + } + } + else + { + generateJSFPage (generatedJSF, realContextPath); + saveFile (file, generatedJSF.toString ()); + } + } + catch (NullPointerException npe) + { + log.info ("Null pointer occured getting \"grids\" out of session: " + + npe); + } + // load session attribute + grids.put (windowNo, gridWindow); + session.setAttribute ("grids", grids); + // next filter + chain.doFilter (request, response); + } + + // creates the window, tabs, and fields for the requested window + private void generateJSFPage(StringBuilder jsfString, String realContextPath) + { + // There is a backing bean called menuBean that we will use for the + // menus of all windows + // TODO change titles to + // title="#{tab_lookup[tabNo].fieldColumnName.tooltip}" + jsfString.append (createCompiereHeader ()); + jsfString.append (createHeader ()); + jsfString + .append ("\n\n\n" + + gridWindow.getName () + + "\n\n" + + "\n\n\n" + + "\n\n\n" + // jsf Messages + + "" + + "\n" + + "\n\n\n
\n" + + "\n" + // toolbar (Maybe extract to method) + + "\n" + + "  \n\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n  \n\n" + + "\n" + + "\n" + + "\n" + + " \n" + + "\n" + + "\n  \n\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n  \n\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n  \n\n" + + "\n" + + "\n" + + "\n" + + "\n  \n\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "  \n" + + "\n" + + "\n" + + "
\n" + // hidden field to store window number + + "\n" + + "\n" + + "\n\n" + + "\n\n\n
\n\n"); + // generate tabs + jsfString.append (generateTabInfo ()); + // end generate tabs + jsfString + .append ("
\n
\n" + + "\n"); + // generate jsp pages for tabs. Each tab has a detail page and a table + // page + createDetailPage (realContextPath); + createTablePage (realContextPath); + int orderSubCount = 1; // used to increment orderSub count + for (int i = 0; i < tabCount; i++) + { + GridTab gridTab = gridWindow.getTab (i); + String tabName = formatNameWithFirstLowerCase (gridTab.getName ()); + jsfString.append ("\n\n\n\n\n" + "\n\n\n\n\n"); + } + jsfString + .append ("\n
\n" + + "
\n\n\n
"); + } + + // Generate GridTabs for JSF page + private StringBuilder generateTabInfo() + { + StringBuilder tabString = new StringBuilder (); + tabCount = gridWindow.getTabCount (); + for (int i = 0; i < tabCount; i++) + { + GridTab gridTab = gridWindow.getTab (i); + if (i == 0) + { + tabString + .append ("\n\n\n\n\n" + + "\n"); + } + else if (gridTab.getTabLevel () == 1) + { + tabString + .append ("baseIndentOneTabStyle unselectedTabStyle\" rendered=\"#{!(uiStateBean.tabNo eq " + + gridTab.getTabNo () + + ")}\"" + + " actionListener=\"#{actionListener_lookup[" + + gridTab.getTabNo () + + "].focus}\" onmouseover=\"this.className='baseIndentOneTabStyle " + + "unselectedMouseOverTabStyle';\" onmouseout=\"this.className='baseIndentOneTabStyle unselectedTabStyle';\" />\n" + + "\n"); + } + else if (gridTab.getTabLevel () == 2) + { + tabString + .append ("baseIndentTwoTabStyle unselectedTabStyle\" rendered=\"#{!(uiStateBean.tabNo eq " + + gridTab.getTabNo () + + ")}\"" + + " actionListener=\"#{actionListener_lookup[" + + gridTab.getTabNo () + + "].focus}\" onmouseover=\"this.className='baseIndentTwoTabStyle " + + "unselectedMouseOverTabStyle';\" onmouseout=\"this.className='baseIndentTwoTabStyle unselectedTabStyle';\" />\n" + + "\n"); + } + tabString + .append ("\n\n"); + } + return tabString; + } + + // Generate Detail jsp page + private void createDetailPage(String realContextPath) + { + File detailFile = null; + for (int i = 0; i < tabCount; i++) + { + StringBuilder detailJSP = new StringBuilder (); + detailJSP.append (createCompiereHeader ()); + detailJSP.append (createHeader ()); + detailJSP.append ("\n"); + GridTab gridTab = gridWindow.getTab (i); + String fileName = formatNameWithFirstLowerCase (gridTab.getName ()) + + "Detail"; + String jsfFile = realContextPath + "window/" + fileName + ".jsp"; + detailFile = new File (jsfFile); + gridTab.dataRefreshAll (); + boolean isSolo = false; // true if not same line as previous + for (int j = 0; j < gridTab.getFieldCount (); j++) + { + GridField gridField = gridTab.getField (j); + // check if displayed + if (gridField.isDisplayed ()) + { + int displayType = gridField.getDisplayType (); + // check display type to genereate jsf code for each + // specific component + switch (displayType) + { + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: // this is a Date format. Comes as Date + + // Time and needs to be chopped in Backing + // Bean + case 16: // this is a Date + Time format. + case 21: // complete address comma seperated ex: + // street, city, state, zip + case 22: + case 29: + case 33: + case 34: + case 35: + case 36: + case 37: + // text box + // check if same line. make sure that it isn't the + // first field. It is possible that the + // first field can have same line checked and that + // would cause formatting issues. + if (gridField.isSameLine () && j != 0) + { + isSolo = false; + } + else + { + if (isSolo) + { + detailJSP + .append ("\n"); + } + detailJSP + .append ("\n"); + isSolo = true; + } + detailJSP + .append ("\n\n"); + // check if same line. if yes and not first field, + // close table row + if (gridField.isSameLine () && j != 0) + { + detailJSP + .append ("\n"); + } + break; + case 17: + case 18: + case 19: + // lookup + // check if same line. make sure that it isn't the + // first field. It is possible that the + // first field can have same line checked and that + // would cause formatting issues. + ArrayList al = gridField.getLookup ().getData ( + true, true, true, true); + if (gridField.isSameLine () && j != 0) + { + isSolo = false; + } + else + { + if (isSolo) + { + detailJSP + .append ("\n"); + } + detailJSP + .append ("\n"); + isSolo = true; + } + detailJSP + .append ("\n\n"); + // check if same line. if yes and not first field, + // close table row + if (gridField.isSameLine () && j != 0) + { + detailJSP + .append ("\n"); + } + break; + case 20: + // Check box + // check if same line. make sure that it isn't the + // first field. It is possible that the + // first field can have same line checked and that + // would cause formatting issues. + if (gridField.isSameLine () && j != 0) + { + isSolo = false; + } + else + { + if (isSolo) + { + detailJSP + .append ("\n"); + } + detailJSP + .append ("\n"); + isSolo = true; + } + detailJSP + .append ("\n"); + // check if same line. if yes and not first field, + // close table row + if (gridField.isSameLine () && j != 0) + { + detailJSP + .append ("\n"); + } + break; + case 23: + case 24: + case 25: + case 27: + case 28: + // custom component + // check if same line. make sure that it isn't the + // first field. It is possible that the + // first field can have same line checked and that + // would cause formatting issues. + if (gridField.isSameLine () && j != 0) + { + isSolo = false; + } + else + { + if (isSolo) + { + detailJSP + .append ("\n"); + } + detailJSP + .append ("\n"); + isSolo = true; + } + detailJSP + .append ("\n"); + // check if same line. if yes and not first field, + // close table row + if (gridField.isSameLine () && j != 0) + { + detailJSP + .append ("\n"); + } + break; + case 30: + // search + // check if same line. make sure that it isn't the + // first field. It is possible that the + // first field can have same line checked and that + // would cause formatting issues. + if (gridField.isSameLine () && j != 0) + { + isSolo = false; + } + else + { + if (isSolo) + { + detailJSP + .append ("\n"); + } + detailJSP + .append ("\n"); + isSolo = true; + } + detailJSP + .append ("\n\n"); + // check if same line. if yes and not first field, + // close table row + if (gridField.isSameLine () && j != 0) + { + detailJSP + .append ("\n"); + } + break; + case 31: + // locator + // check if same line. make sure that it isn't the + // first field. It is possible that the + // first field can have same line checked and that + // would cause formatting issues. + if (gridField.isSameLine () && j != 0) + { + isSolo = false; + } + else + { + if (isSolo) + { + detailJSP + .append ("\n"); + } + detailJSP + .append ("\n"); + isSolo = true; + } + detailJSP + .append ("\n\n"); + // check if same line. if yes and not first field, + // close table row + if (gridField.isSameLine () && j != 0) + { + detailJSP + .append ("\n"); + } + break; + case 32: + // image + // check if same line. make sure that it isn't the + // first field. It is possible that the + // first field can have same line checked and that + // would cause formatting issues. + if (gridField.isSameLine () && j != 0) + { + isSolo = false; + } + else + { + if (isSolo) + { + detailJSP + .append ("\n"); + } + detailJSP + .append ("\n"); + isSolo = true; + } + detailJSP + .append ("\n\n"); + // check if same line. if yes and not first field, + // close table row + if (gridField.isSameLine () && j != 0) + { + detailJSP + .append ("\n"); + } + break; + default: + log.severe ("Display Type not handled for " + + gridField.getColumnName () + + " with display type: " + + gridField.getDisplayType ()); + break; + } + } + } + detailJSP.append ("
" + + "\n" + + "\n
\n" + + "\n\n\n
\n" + + "\n" + + "\n" + + "
" + + "\n" + + " \n
" + + "\n" + + "\n
" + + "\n" + + "\n
" + + "\n" + + "\n
"); + saveFile (detailFile, detailJSP.toString ()); + } + } + + // Generate Table jsp page + private void createTablePage(String realContextPath) + { + File tableFile = null; + for (int i = 0; i < tabCount; i++) + { + StringBuilder tableJSP = new StringBuilder (); + tableJSP.append (createCompiereHeader ()); + tableJSP.append (createHeader ()); + GridTab gridTab = gridWindow.getTab (i); + String fileName = formatNameWithFirstLowerCase (gridTab.getName ()) + + "Table"; + String jsfFile = realContextPath + "window/" + fileName + ".jsp"; + tableFile = new File (jsfFile); + gridTab.dataRefreshAll (); + // counter for subscripts + int subscriptCount = 0; + tableJSP + .append ("\n"); + for (int j = 0; j < gridTab.getFieldCount (); j++) + { + GridField gridField = gridTab.getField (j); + tableJSP + .append ("\n\n"); + // check if displayed + if (gridField.isDisplayed ()) + { + int displayType = gridField.getDisplayType (); + // check display type to genereate jsf code for each + // specific component + switch (displayType) + { + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: // this is a Date format. Comes as Date + + // Time and needs to be chopped in Backing + // Bean + case 16: // this is a Date + Time format. + case 21: // complete address comma seperated ex: + // street, city, state, zip + case 22: + case 29: + case 33: + case 34: + case 35: + case 36: + case 37: + // text box + tableJSP.append ("\n"); + break; + case 17: + case 18: + case 19: + // lookup + tableJSP + .append ("\n\n\n"); + break; + case 20: + // check box + tableJSP + .append ("\n"); + break; + case 23: + case 24: + case 25: + case 27: + case 28: + // custom component + tableJSP.append ("\n"); + break; + case 30: + // search + tableJSP + .append ("\n"); + subscriptCount++; + break; + case 31: + // locator + tableJSP + .append ("\n"); + subscriptCount++; + break; + case 32: + // image + tableJSP + .append ("\n"); + subscriptCount++; + break; + default: + log.severe ("Display Type not handled for " + + gridField.getColumnName () + + " with display type: " + + gridField.getDisplayType ()); + subscriptCount++; + break; + } + } + tableJSP.append ("\n"); + } + tableJSP.append (""); + saveFile (tableFile, tableJSP.toString ()); + } + } + + // Save GridWindow jsf test file + private void saveFile(File file, String generatedJSF) + { + try + { + FileWriter out = new FileWriter (file); + out.write (generatedJSF); + out.flush (); + out.close (); + } + catch (IOException ioe) + { + log.severe ("Error " + ioe.toString () + + " occurred in saveGridWindow"); + } + } + + // format name of file or tab + private String formatNameWithFirstLowerCase(String name) + { + String[] tempNameArray = name.split (" "); + for (int i = 0; i < tempNameArray.length; i++) + { + if (i == 0) + { + name = tempNameArray[i].toLowerCase (); + } + else + { + name += tempNameArray[i]; + } + } + return name; + } + + // compiere header + private StringBuilder createCompiereHeader() + { + StringBuilder compiereHeader = new StringBuilder (); + compiereHeader + .append ("<%--/*************************************************************\n" + + " **********\n" + + " *******\n" + + " * Product: Compiere ERP & CRM Smart Business Solution\n" + + " * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved.\n" + + " * This program is free software; you can redistribute it and/or modify it\n" + + " * under the terms version 2 of the GNU General Public License as published\n" + + " * by the Free Software Foundation. This program is distributed in the hope\n" + + " * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied\n" + + " * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" + + " * See the GNU General Public License for more details.\n" + + " * You should have received a copy of the GNU General Public License along\n" + + " * with this program; if not, write to the Free Software Foundation, Inc.,\n" + + " * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.\n" + + " * You may reach us at: ComPiere, Inc. - http://www.compiere.org/license.html\n" + + " * 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@compiere.org\n" + + " **************************************************************\n" + + " **********\n" + " *****/--%>\n"); + return compiereHeader; + } + + // page header + private StringBuilder createHeader() + { + StringBuilder headerString = new StringBuilder (); + headerString + .append ("<%@page contentType=\"text/html\"%>\n<%@page pageEncoding=\"UTF-8\"%>\n" + + "<%@ taglib uri=\"http://java.sun.com/jsf/core\" prefix=\"f\"%>\n" + + "<%@ taglib uri=\"http://java.sun.com/jsf/html\" prefix=\"h\"%>\n" + + "<%@ taglib uri=\"http://myfaces.apache.org/tomahawk\" prefix=\"t\"%>\n"); + return headerString; + } + + // Get GridWindow TimeStamp + private long getGridWindowTimeStamp() + { + Timestamp timeStamp = gridWindow.getModelUpdated (true); + if (timeStamp.equals (null)) + { + log.severe ("Could not get GridWindow TimeStamp"); + } + return timeStamp.getTime (); + } +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/MenuBean.java b/serverApps/src/main/servlet/org/compiere/jsf/MenuBean.java new file mode 100755 index 0000000000..f3deeee087 --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/MenuBean.java @@ -0,0 +1,134 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import java.util.ArrayList; +import java.util.List; +import org.apache.myfaces.custom.navmenu.NavigationMenuItem; + +import org.apache.log4j.Logger; + +/** + * provides a model of the main menu bar + * + * @author rfreden + */ +public class MenuBean +{ + private static final Logger log=Logger.getLogger(MenuBean.class); + + private List menu; + + // label, icon, action + // all three null for menu break + // first element is the submenu title + private static final String[][] fileMenu= { { "File", null, null }, + { "Print Screen", "/images/PrintScreen16.gif", null }, + { "Screen Shot", "/images/ScreenShot16.gif", null }, + { "Report", "/images/Report16.gif", null }, { "Print", "/images/Print16.gif", null }, + { null, null, null }, { "End", "/images/End16.gif", null }, + { "Exit", "/images/Exit16.gif", null } }; + + private static final String[][] editMenu= { { "Edit", null, null }, + { "New Record", "/images/New16.gif", null }, { "Save", "/images/Save16.gif", null }, + { null, null, null }, { "Copy Record", "/images/Copy16.gif", null }, + { "Delete Record", "/images/Delete16.gif", null }, + { "Undo Changes", "/images/Undo16.gif", null }, + { "Requery", "/images/Refresh16.gif", null }, { null, null, null }, + { "Look Up Record", "/images/Find16.gif", null } }; + + private static final String[][] viewMenu= { { "View", null, null }, + { "Product Info", "/images/Product16.gif", null }, + { "Business Partner Info", "/images/BPartner16.gif", null }, + { "Account Info", "/images/InfoAccount16.gif", null }, + { "Schedule Info", "/images/InfoSchedule16.gif", null }, { null, null, null }, + { "Order Info", "/images/Info16.gif", null }, + { "Invoice Info", "/images/Info16.gif", null }, + { "Shipment Info", "/images/Info16.gif", null }, + { "Payment Info", "/images/Info16.gif", null }, + { "Cash Journal Info", "/images/Info16.gif", null }, + { "Resource Info", "/images/Info16.gif", null }, + { "Asset Info", "/images/Info16.gif", null }, { null, null, null }, + { "Attachment", "/images/Attachment16.gif", null }, + { "History Records", "/images/History16.gif", null }, { null, null, null }, + { "Grid Toggle", "/images/Multi16.gif", null } }; + + private static final String[][] goMenu= { { "Go", null, null }, + { "First Record", "/images/First16.gif", null }, + { "Previous Record", "/images/Previous16.gif", null }, + { "Next Record", "/images/Next16.gif", null }, + { "Last Record", "/images/Last16.gif", null }, { null, null, null }, + { "Parent Record", "/images/Parent16.gif", null }, + { "Detail Record", "/images/Detail16.gif", null }, { null, null, null }, + { "Zoom Across (Where Used)", "/images/ZoomAcross16.gif", null }, + { "Check Requests", "/images/Request16.gif", null }, + { "Archived Documents/Reports", "/images/Archive16.gif", null }, + { "Menu", "/images/Home16.gif", null } }; + + private static final String[][] toolsMenu= { { "Tools", null, null }, + { "Calculator", "/images/Calculator16.gif", null }, + { "Calendar", "/images/Calendar16.gif", null }, + { "Editor", "/images/Editor16.gif", null }, { "Script", "/images/Script16.gif", null }, + { "Active Workflows", "/images/WorkFlow16.gif", null }, { null, null, null }, + { "Preference", "/images/Preference16.gif", null } }; + + private static final String[][] helpMenu= { { "Help", null, null }, + { "Help", "/images/Help16.gif", null }, { "Online", "/images/Online16.gif", null }, + { "Email Support", "/images/EMailSupport16.gif", null }, + { "About", "/images/About16.gif", null } }; + + /** Creates a new instance of MenuBean */ + public MenuBean() + { + menu=new ArrayList(); + menu.add(getNavigationItemListFromArray(fileMenu)); + menu.add(getNavigationItemListFromArray(editMenu)); + menu.add(getNavigationItemListFromArray(viewMenu)); + menu.add(getNavigationItemListFromArray(goMenu)); + menu.add(getNavigationItemListFromArray(toolsMenu)); + menu.add(getNavigationItemListFromArray(helpMenu)); + } + + public List getMenu() + { + return menu; + } + + private NavigationMenuItem getNavigationItemListFromArray(String[][] sa) + { + NavigationMenuItem root=new NavigationMenuItem(sa[0][0], sa[0][2], sa[0][1], false); + List tmp=new ArrayList(); + for (int i=1; i, for windowNo and tab state string + * but... this class should be the only interface to that (currently there is an el expression that looks like #{sessionScope.tabNo[windowNo]} ) + * this object is _only valid for the windowNo it is instantiated from_ + * the class furthermore should be the interface to windowNo, which is a request parameter + * @author rfreden + * + */ +public class TabStateManager +{ + private static final CLogger log=CLogger.getCLogger(TabStateManager.class); + + // the map should be a non clobberable singleton + private static Map tabNo; + + private FacesContext facesContext; + + public TabStateManager(FacesContext fc) + { + facesContext=fc; + if(tabNo==null) + { + // if it doesn't exist in the session, then instantiate it and put it there + if((tabNo=(Map)facesContext.getExternalContext().getSessionMap().get("tabNo"))==null) + { + tabNo=new HashMap(); + facesContext.getExternalContext().getSessionMap().put("tabNo",tabNo); + } + } + } + + public UIStateBean getUIState() + { + return (UIStateBean)facesContext.getApplication().getVariableResolver().resolveVariable(facesContext,"uiStateBean"); + } +} diff --git a/serverApps/src/main/servlet/org/compiere/jsf/UIStateBean.java b/serverApps/src/main/servlet/org/compiere/jsf/UIStateBean.java new file mode 100755 index 0000000000..9de96fbc16 --- /dev/null +++ b/serverApps/src/main/servlet/org/compiere/jsf/UIStateBean.java @@ -0,0 +1,100 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.jsf; + +import java.io.Serializable; + +import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; + +import org.compiere.util.CLogger; + +/** + * holds state for a window; currently it tracks only the windowNo attribute, provided on initial load + * an instance of this class should be available for any window page, as it is persisted throughout the view existence via t:saveState + * @author rfreden + * + */ +public class UIStateBean implements Serializable +{ + private static final long serialVersionUID=2930846164351L; + + private static final CLogger log=CLogger.getCLogger(UIStateBean.class); + + // TODO: this should be an Integer + private String windowNo; + + private boolean gridView; + + private int tabNo; + + public UIStateBean() + { + // int and boolean default initializers put this initial state at tab0Detail + String[] s=(String[])FacesContext.getCurrentInstance().getExternalContext().getRequestParameterValuesMap().get("windowNo"); + if(s!=null) + { + windowNo=s[0]; + log.info("got windowNo "+windowNo); + } + } + + public void setWindowNo(String w) + { + log.info("setting windowNo "+w); + windowNo=w; + } + + public String getWindowNo() + { + //log.info("getting windowNo "+windowNo); + return windowNo; + } + + public Boolean getGridView() + { + return gridView; + } + + public void setGridView(Boolean b) + { + gridView=b; + } + + public Integer getTabNo() + { + return tabNo; + } + + public void setTabNo(Integer i) + { + tabNo=i; + } + + public String getTabState() + { + String s="tab"+String.valueOf(tabNo)+(gridView?"Table":"Detail"); + log.info("returning "+s); + return s; + } + + public void toggleGridView(ActionEvent ae) + { + log.info("called"); + gridView=!gridView; + } +}