[richfaces-svn-commits] JBoss Rich Faces SVN: r2167 - in trunk/samples/richfaces-demo/src/main: java/org/richfaces/demo/extendeddatamodel and 3 other directories.

richfaces-svn-commits at lists.jboss.org richfaces-svn-commits at lists.jboss.org
Wed Aug 8 23:04:55 EDT 2007


Author: ishabalov
Date: 2007-08-08 23:04:55 -0400 (Wed, 08 Aug 2007)
New Revision: 2167

Added:
   trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/
   trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionDataModel.java
   trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionDataProvider.java
   trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionItem.java
   trunk/samples/richfaces-demo/src/main/webapp/richfaces/dataTable/extended-data-model.xhtml
Modified:
   trunk/samples/richfaces-demo/src/main/webapp/WEB-INF/
   trunk/samples/richfaces-demo/src/main/webapp/WEB-INF/faces-config.xml
   trunk/samples/richfaces-demo/src/main/webapp/richfaces/dataTable.xhtml
Log:
Added sample for extended data model

Added: trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionDataModel.java
===================================================================
--- trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionDataModel.java	                        (rev 0)
+++ trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionDataModel.java	2007-08-09 03:04:55 UTC (rev 2167)
@@ -0,0 +1,191 @@
+package org.richfaces.demo.extendeddatamodel;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.context.FacesContext;
+
+import org.ajax4jsf.model.DataVisitor;
+import org.ajax4jsf.model.Range;
+import org.ajax4jsf.model.SequenceRange;
+import org.ajax4jsf.model.SerializableDataModel;
+/**
+ * 
+ * @author ias
+ * This is example class that intended to demonstrate use of ExtendedDataModel and SerializableDataModel.
+ * This implementation intended to be used as a request scope bean. However, it actually provides serialized
+ * state, so on a post-back we do not load data from the data provider. Instead we use whatever data was used 
+ * during rendering.
+ * This data model intended to be used together with Data Provider, which is responsible for actual data load 
+ * from the database using specific filtering and sorting. Normally it suppose to be in either session, or conversation
+ * scope.
+ */
+public class AuctionDataModel extends SerializableDataModel {
+	
+	private AuctionDataProvider dataProvider;
+	private Integer currentPk;
+	private Map<Integer,AuctionItem> wrappedData = new HashMap<Integer,AuctionItem>();
+	private List<Integer> wrappedKeys = null;
+	private boolean detached = false;
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -1956179896877538628L;
+
+	/**
+	 * This method never called from framework.
+	 * (non-Javadoc)
+	 * @see org.ajax4jsf.model.ExtendedDataModel#getRowKey()
+	 */
+	@Override
+	public Object getRowKey() {
+		return currentPk;
+	}
+	/**
+	 * This method normally called by Visitor before request Data Row.
+	 */
+	@Override
+	public void setRowKey(Object key) {
+		this.currentPk = (Integer) key;
+		
+	}
+	/**
+	 * This is main part of Visitor pattern. Method called by framework many times during request processing. 
+	 */
+	@Override
+	public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
+		int firstRow = ((SequenceRange)range).getFirstRow();
+		int numberOfRows = ((SequenceRange)range).getRows();
+		if (detached) { // Is this serialized model
+// Here we just ignore current Rage and use whatever data was saved in serialized model. 
+// Such approach uses much more getByPk() operations, instead of just one request by range.
+// Concrete case may be different from that, so you can just load data from data provider by range.
+// We are using wrappedKeys list only to preserve actual order of items.
+			for (Integer key:wrappedKeys) {
+				setRowKey(key);
+				visitor.process(context, key, argument);
+			}
+		} else { // if not serialized, than we request data from data provider
+			wrappedKeys = new ArrayList<Integer>();
+			for (AuctionItem item:dataProvider.getItemsByrange(new Integer(firstRow), numberOfRows, null, true)) {
+				wrappedKeys.add(item.getPk());
+				wrappedData.put(item.getPk(), item);
+				visitor.process(context, item.getPk(), argument);
+			}
+		}
+	}
+	/**
+	 * This method must return actual data rows count from the Data Provider. It is used by pagination control
+	 * to determine total number of data items.
+	 */
+	private Integer rowCount; // better to buffer row count locally
+	@Override
+	public int getRowCount() {
+		if (rowCount==null) {
+			rowCount = new Integer(getDataProvider().getRowCount());
+			return rowCount.intValue();
+		} else {
+			return rowCount.intValue();
+		}
+	}
+	/**
+	 * This is main way to obtain data row. It is intensively used by framework. 
+	 * We strongly recommend use of local cache in that method. 
+	 */
+	@Override
+	public Object getRowData() {
+		if (currentPk==null) {
+			return null;
+		} else {
+			AuctionItem ret = wrappedData.get(currentPk);
+			if (ret==null) {
+				ret = getDataProvider().getAuctionItemByPk(currentPk);
+				wrappedData.put(currentPk, ret);
+				return ret;
+			} else {
+				return ret;
+			}
+		}
+	}
+
+	/**
+	 * Unused rudiment from old JSF staff.
+	 */
+	@Override
+	public int getRowIndex() {
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * Unused rudiment from old JSF staff.
+	 */
+	@Override
+	public Object getWrappedData() {
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * Never called by framework.
+	 */
+	@Override
+	public boolean isRowAvailable() {
+		if (currentPk==null) {
+			return false;
+		} else {
+			return getDataProvider().hasAuctionItemByPk(currentPk);
+		}
+	}
+
+	/**
+	 * Unused rudiment from old JSF staff.
+	 */
+	@Override
+	public void setRowIndex(int rowIndex) {
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * Unused rudiment from old JSF staff.
+	 */
+	@Override
+	public void setWrappedData(Object data) {
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * This method suppose to produce SerializableDataModel that will be serialized into View State and used on a post-back.
+	 * In current implementation we just mark current model as serialized. In more complicated cases we may need to 
+	 * transform data to actually serialized form.
+	 */
+	public  SerializableDataModel getSerializableModel(Range range) {
+		if (wrappedKeys!=null) {
+			detached = true;
+// Some activity to detach persistent data from wrappedData map may be taken here.
+// In that specific case we are doing nothing.
+			return this; 
+		} else {
+			return null;
+		}
+	}
+	/**
+	 * This is helper method that is called by framework after model update. In must delegate actual database update to 
+	 * Data Provider.
+	 */
+	@Override
+	public void update() {
+		getDataProvider().update();
+	}
+
+	public AuctionDataProvider getDataProvider() {
+		return dataProvider;
+	}
+
+	public void setDataProvider(AuctionDataProvider dataProvider) {
+		this.dataProvider = dataProvider;
+	}
+
+}

Added: trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionDataProvider.java
===================================================================
--- trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionDataProvider.java	                        (rev 0)
+++ trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionDataProvider.java	2007-08-09 03:04:55 UTC (rev 2167)
@@ -0,0 +1,100 @@
+package org.richfaces.demo.extendeddatamodel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.richfaces.demo.common.RandomDataHelper;
+
+public class AuctionDataProvider {
+	
+	private String allDescriptions[] = {
+			"Digital temperature sensor IC LM75A SOIC8 +Free adapter",
+			"MC34063 Adjustable Power Supply DC-DC Converters 5x",
+			"100x Ultra Bright White LEDs, 5mm, Clear",
+			"100x Ultra Bright Blue LEDs, 5mm, Clear",
+			"100x Ultra Bright Yellow LEDs, 5mm, Clear",
+			"100x Ultra Bright Red LEDs, 5mm, Clear",
+			"High quality Universal Programmer Development Board",
+			"Lot of 10pcs 8x8 dot-matrix 3mm dia LED display bicolor",
+			"100x Ultra Bright Blue LEDs, 5mm, Clear",
+			"40pcs 74HC164 165 573 595 Shift register & latch IC kit",
+			"Electric Nail Manicure Drill File 4 Acrylic Polish Nail",
+			"LE-DS007 100x Ultra Bright VIOLET ( UV ) LED LEDs, 5mm",
+			"LE-DS007 100x Ultra Bright VIOLET ( UV ) LED LEDs, 5mm",
+			"Fantastic High brightness Cluster with 8pcs LED (Green)",
+			"100x Ultra Bright Yellow LEDs, 5mm, Clear",
+			"High brightness 1 pcs 3W 80 lm Lumen LED White",
+			"2X ATMEL ATMEGA128-16AU Microcontroller and 2x 64-TQFP",
+			"20pcs IRF530 & IRF9630 power mosfet kit",
+			"Electrolytic Capacitors Radial SMD SMT assorted kit",
+			"100 pcs Ultra Bright Mixed LEDs, 5mm, Clear",
+			"Lot of 80 pcs 8 values (1uH~1mH) color wheel inductors",
+			"Lot of 100pcs 4 values (4.7uH~220uH) DIP fixed inductor",
+			"10pcs 8x8 dot-matrix 3mm dia LED display bicolor",
+			"(SMD 0805) 50 Value Resistors + 32 Value Capacitors Kit",
+			"Fantastic High brightness Cluster with 24pcs LED (Red)",
+			"100x Ultra Bright Green LEDs, 5mm, Clear",
+			"100x Ultra Bright Blue LEDs, 5mm, Clear",
+			"Double-row Straight 20x male and 10x female pin header",
+			"NEW 30pcs HEAT SINKS ,50pcs insulation bushing and film",
+			"0.2% Class A Platinum Resistance Thermometers PT100"
+	};
+	private List<AuctionItem> allItems = null;
+	private static final int VOLUME = 200;
+	
+	private synchronized void initData() {
+		List<AuctionItem> data = new ArrayList<AuctionItem>();
+		for (int counter=0; counter<VOLUME; counter++) {
+			AuctionItem item = new AuctionItem(new Integer(counter));
+			item.setDescription((String)RandomDataHelper.random(allDescriptions));
+			item.setHighestBid(new Double(RandomDataHelper.random(10, 100)));
+			item.setQtyAvialable(new Integer(RandomDataHelper.random(1, 20)));
+			data.add(item);
+			
+		}
+		allItems = data;
+	}
+
+	public List<AuctionItem> getAllItems() {
+		if (allItems!=null && allItems.size()>0) {
+			return allItems;
+		} else {
+			initData();
+			return allItems;
+		}
+	}
+	
+	public AuctionItem getAuctionItemByPk(Integer pk) {
+		for (AuctionItem item:getAllItems()) {
+			if (item.getPk().equals(pk)) {
+				return item;
+			}
+		}
+		throw new RuntimeException("Auction Item pk="+pk.toString()+" not found");
+	}
+	public boolean hasAuctionItemByPk(Integer pk) {
+		for (AuctionItem item:getAllItems()) {
+			if (item.getPk().equals(pk)) {
+				return true;
+			}
+		}
+		return false;
+		
+	}
+	
+	public List<AuctionItem> getItemsByrange(Integer startPk, int numberOfRows, String sortField, boolean ascending) {
+		List<AuctionItem> ret = new ArrayList<AuctionItem>();
+		for (int counter=0; counter<numberOfRows; counter++) {
+			ret.add(getAllItems().get(startPk.intValue()+counter));
+		}
+		return ret;
+	}
+	
+	public void update() {
+		// nothing need to do
+	}
+	
+	public int getRowCount() {
+		return getAllItems().size();
+	}
+}

Added: trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionItem.java
===================================================================
--- trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionItem.java	                        (rev 0)
+++ trunk/samples/richfaces-demo/src/main/java/org/richfaces/demo/extendeddatamodel/AuctionItem.java	2007-08-09 03:04:55 UTC (rev 2167)
@@ -0,0 +1,100 @@
+package org.richfaces.demo.extendeddatamodel;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+public class AuctionItem {
+	private Integer pk;
+	private String description;
+	private Double bid;
+	private Double highestBid;
+	private Integer qtyRequested;
+	private Integer qtyAvialable;
+	private UIComponent bidInput;
+	private UIComponent qtyInput;
+	private boolean won = false;
+	private boolean loose = false;
+	private Double amount;
+	
+	@SuppressWarnings("unused")
+	private AuctionItem() {};
+	
+	public AuctionItem(Integer pk) {
+		this.pk = pk;
+	}
+	
+	public Integer getPk() {
+		return pk;
+	}
+	public String getDescription() {
+		return description;
+	}
+	public void setDescription(String description) {
+		this.description = description;
+	}
+	public Double getBid() {
+		return bid;
+	}
+	public void setBid(Double bid) {
+		this.bid = bid;
+	}
+	public Double getHighestBid() {
+		return highestBid;
+	}
+	public void setHighestBid(Double highestBid) {
+		this.highestBid = highestBid;
+	}
+	public Integer getQtyRequested() {
+		return qtyRequested;
+	}
+	public void setQtyRequested(Integer qty) {
+		this.qtyRequested = qty;
+	}
+	public Double getAmount() {
+		return this.amount;
+	}
+	public Integer getQtyAvialable() {
+		return qtyAvialable;
+	}
+	public void setQtyAvialable(Integer qtyAvialable) {
+		this.qtyAvialable = qtyAvialable;
+	}
+	public String placeBid() {
+		if (qtyRequested!=null && bid!=null) {
+			System.out.println("place bid for pk="+getPk()+" bid="+getBid()+" qty="+getQtyRequested());
+			FacesContext ctx = FacesContext.getCurrentInstance();
+			if (qtyRequested>qtyAvialable) {
+				ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"Requested quantity is grater that avialable quantity","You cannot request more auction items, that actually avialable on auction"));
+				won = loose = false;
+			} else if (bid<=highestBid) {
+				ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Bid amount is lower that highest bid","You need to bid amount higher that highest bid"));
+				won = false;
+				loose = true;
+			} else {
+				highestBid = bid;
+				won = true;
+				loose = false;
+				amount = qtyRequested*bid;
+			}
+		}
+		return null;
+	}
+
+	public UIComponent getBidInput() {
+		return bidInput;
+	}
+
+	public void setBidInput(UIComponent bidInput) {
+		this.bidInput = bidInput;
+	}
+
+	public UIComponent getQtyInput() {
+		return qtyInput;
+	}
+
+	public void setQtyInput(UIComponent qtyInput) {
+		this.qtyInput = qtyInput;
+	}
+	
+}


Property changes on: trunk/samples/richfaces-demo/src/main/webapp/WEB-INF
___________________________________________________________________
Name: svn:ignore
   + .faces-config.xml.jsfdia


Modified: trunk/samples/richfaces-demo/src/main/webapp/WEB-INF/faces-config.xml
===================================================================
--- trunk/samples/richfaces-demo/src/main/webapp/WEB-INF/faces-config.xml	2007-08-09 02:20:33 UTC (rev 2166)
+++ trunk/samples/richfaces-demo/src/main/webapp/WEB-INF/faces-config.xml	2007-08-09 03:04:55 UTC (rev 2167)
@@ -184,4 +184,19 @@
   <managed-bean-class>org.richfaces.demo.ajaxSamples.rsBean</managed-bean-class>
   <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
+ <managed-bean>
+  <managed-bean-name>auctionDataModel</managed-bean-name>
+  <managed-bean-class>org.richfaces.demo.extendeddatamodel.AuctionDataModel</managed-bean-class>
+  <managed-bean-scope>request</managed-bean-scope>
+  <managed-property>
+   <property-name>dataProvider</property-name>
+   <property-class>org.richfaces.demo.extendeddatamodel.AuctionDataProvider</property-class>
+   <value>#{auctionDataProvider}</value>
+  </managed-property>
+ </managed-bean>
+ <managed-bean>
+  <managed-bean-name>auctionDataProvider</managed-bean-name>
+  <managed-bean-class>org.richfaces.demo.extendeddatamodel.AuctionDataProvider</managed-bean-class>
+  <managed-bean-scope>session</managed-bean-scope>
+ </managed-bean>
 </faces-config>

Added: trunk/samples/richfaces-demo/src/main/webapp/richfaces/dataTable/extended-data-model.xhtml
===================================================================
--- trunk/samples/richfaces-demo/src/main/webapp/richfaces/dataTable/extended-data-model.xhtml	                        (rev 0)
+++ trunk/samples/richfaces-demo/src/main/webapp/richfaces/dataTable/extended-data-model.xhtml	2007-08-09 03:04:55 UTC (rev 2167)
@@ -0,0 +1,72 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+	xmlns:ui="http://java.sun.com/jsf/facelets"
+	xmlns:h="http://java.sun.com/jsf/html"
+	xmlns:f="http://java.sun.com/jsf/core"
+	xmlns:a4j="http://richfaces.org/a4j"
+	xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+	<ui:composition template="/templates/component-sample.xhtml">
+		<ui:define name="sample">
+			<p>Some explanation how to use ExtendedDataModel will be here
+			</p>
+			<div class="sample-container" >
+				<rich:messages />
+				<h:form>
+				<rich:datascroller for="auction" maxPages="5"/>
+				<rich:spacer height="30" />				
+				<rich:dataTable id="auction" value="#{auctionDataModel}" var="item" rows="25"> 
+					<rich:column>
+						<f:facet name="header">
+							<h:outputText value="Description"/>
+						</f:facet>
+						<h:outputText value="#{item.description}"/>
+					</rich:column>
+					<rich:column>
+						<f:facet name="header">
+							<h:outputText value="Highest Bid"/>
+						</f:facet>
+						<h:outputText id="highestBid" value="#{item.highestBid}">
+							<f:convertNumber pattern="$#,##0.00"/>
+						</h:outputText>
+					</rich:column>
+					<rich:column>
+						<f:facet name="header">
+							<h:outputText value="Qty Avialable"/>
+						</f:facet>
+						<h:outputText value="#{item.qtyAvialable}"/>
+					</rich:column>
+					<rich:column>
+						<f:facet name="header">
+							<h:outputText value="Your Bid"/>
+						</f:facet>
+						<h:inputText id="bid" value="#{item.bid}">
+							<f:convertNumber />
+						</h:inputText>
+						<a4j:commandLink action="#{item.placeBid}" value="Bid!" reRender="bid,qty,amount,highestBid" />
+					</rich:column>
+					<rich:column>
+						<f:facet name="header">
+							<h:outputText value="Your Qty"/>
+						</f:facet>
+						<h:inputText id="qty" value="#{item.qtyRequested}">
+							<f:convertNumber />
+						</h:inputText>
+					</rich:column>
+					<rich:column>
+						<f:facet name="header">
+							<h:outputText value="Amount"/>
+						</f:facet>
+						<h:outputText id="amount" value="#{item.amount}" >
+							<f:convertNumber pattern="$#,##0.00"/>
+						</h:outputText>
+					</rich:column>
+				</rich:dataTable>
+				</h:form>
+			</div>
+		</ui:define>
+		<ui:define name="sources">
+				Here is a fragment of page sources for the given example:
+				<iframe src="${facesContext.externalContext.requestContextPath}/richfaces/dataTable/source/usage.html" class="source_frame"/>
+		</ui:define>
+	</ui:composition>
+</html>

Modified: trunk/samples/richfaces-demo/src/main/webapp/richfaces/dataTable.xhtml
===================================================================
--- trunk/samples/richfaces-demo/src/main/webapp/richfaces/dataTable.xhtml	2007-08-09 02:20:33 UTC (rev 2166)
+++ trunk/samples/richfaces-demo/src/main/webapp/richfaces/dataTable.xhtml	2007-08-09 03:04:55 UTC (rev 2167)
@@ -11,6 +11,9 @@
 			<rich:tab label="Usage">
 				<ui:include src="/richfaces/dataTable/usage.xhtml"/>
 			</rich:tab>			
+			<rich:tab label="Extended Data Model">
+				<ui:include src="/richfaces/dataTable/extended-data-model.xhtml"/>
+			</rich:tab>			
 		</rich:tabPanel>
 	</ui:define>
 </ui:composition>




More information about the richfaces-svn-commits mailing list