Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Programming

1083 Articles
article-image-networking-performance-design
Packt
23 Aug 2013
18 min read
Save for later

Networking Performance Design

Packt
23 Aug 2013
18 min read
(For more resources related to this topic, see here.) Device and I/O virtualization involves managing the routing of I/O requests between virtual devices and the shared physical hardware. Software-based I/O virtualization and management, in contrast to a direct pass through to the hardware, enables a rich set of features and simplified management. With networking, virtual NICs and virtual switches create virtual networks between virtual machines which are running on the same host without the network traffic consuming bandwidth on the physical network NIC teaming consists of multiple, physical NICs and provides failover and load balancing for virtual machines. Virtual machines can be seamlessly relocated to different systems by using VMware vMotion, while keeping their existing MAC addresses and the running state of the VM. The key to effective I/O virtualization is to preserve these virtualization benefits while keeping the added CPU overhead to a minimum. The hypervisor virtualizes the physical hardware and presents each virtual machine with a standardized set of virtual devices. These virtual devices effectively emulate well-known hardware and translate the virtual machine requests to the system hardware. This standardization on consistent device drivers also helps with virtual machine standardization and portability across platforms, because all virtual machines are configured to run on the same virtual hardware, regardless of the physical hardware in the system. In this article we will discuss the following: Describe various network performance problems Discuss the causes of network performance problems Propose solutions to correct network performance problems Designing a network for load balancing and failover for vSphere Standard Switch The load balancing and failover policies that are chosen for the infrastructure can have an impact on the overall design. Using NIC teaming we can group several physical network adapters attached to a vSwitch. This grouping enables load balancing between the different physical NICs and provides fault tolerance if a card or link failure occurs. Network adapter teaming offers a number of available load balancing and load distribution options. Load balancing is load distribution based on the number of connections, not on network traffic. In most cases, load is managed only for the outgoing traffic and balancing is based on three different policies: Route based on the originating virtual switch port ID (default) Route based on the source MAC hash Route based on IP hash Also, we have two network failure detection options and those are: Link status only Beacon probing Getting ready To step through this recipe, you will need one or more running ESXi hosts, a vCenter Server, and a working installation of vSphere Client. No other prerequisites are required. How to do it... To change the load balancing policy and to select the right one for your environment, and also select the appropriate failover policy, you need to follow the proceeding steps: Open up your VMware vSphere Client. Log in to the vCenter Server. On the left hand side, choose any ESXi Server and choose configuration from the right hand pane. Click on the Networking section and select the vSwitch for which you want to change the load balancing and failover settings. You may wish to override this per port group level as well. Click on Properties. Select the vSwitch and click on Edit. Go to the NIC Teaming tab. Select one of the available policies from the Load Balancing drop-down menu. Select one of the available policies on the Network Failover Detection drop-down menu. Click on OK to make it effective. How it works... Route based on the originating virtual switch port ID (default) In this configuration, load balancing is based on the number of physical network cards and the number of virtual ports used. With this configuration policy, a virtual network card connected to a vSwitch port will always use the same physical network card. If a physical network card fails, the virtual network card is redirected to another physical network card. You typically do not see the individual ports on a vSwitch. However, each vNIC that gets connected to a vSwitch is implicitly using a particular port on the vSwitch. (It's just that there's no reason to ever configure which port, because that is always done automatically.) It does a reasonable job of balancing your egress uplinks for the traffic leaving an ESXi host as long as all the virtual machines using these uplinks have similar usage patterns. It is important to note that port allocation occurs only when a VM is started or when a failover occurs. Balancing is done based on a port's occupation rate at the time the VM starts up. This means that which pNIC is selected for use by this VM is determined at the time the VM powers on based on which ports in the vSwitch are occupied at the time. For example, if you started 20 VMs in a row on a vSwitch with two pNICs, the odd-numbered VMs would use the left pNIC and the even-numbered VMs would use the right pNIC and that would persist even if you shut down all the even-numbered VMs; the left pNIC, would have all the VMs and the right pNIC would have none. It might happen that two heavily-loaded VMs are connected to the same pNIC, thus load is not balanced. This policy is the easiest one and we always call for the simplest one to map it to a best operational simplification. Now when speaking of this policy, it is important to understand that if, for example, teaming is created with two 1 GB cards, and if one VM consumes more than one card's capacity, a performance problem will arise because traffic greater than 1 Gbps will not go through the other card, and there will be an impact on the VMs sharing the same port as the VM consuming all resources. Likewise, if two VMs each wish to use 600 Mbps and they happen to go to the first pNIC, the first pNIC cannot meet the 1.2 Gbps demand no matter how idle the second pNIC is. Route based on source MAC hash This principle is the same as the default policy but is based on the number of MAC addresses. This policy may put those VM vNICs on the same physical uplink depending on how the MAC hash is resolved. For MAC hash, VMware has a different way of assigning ports. It's not based on the dynamically changing port (after a power off and power on the VM usually gets a different vSwitch port assigned), but is instead based on fixed MAC address. As a result one VM is always assigned to the same physical NIC unless the configuration is not changed. With the port ID, the VM could get different pNICs after a reboot or VMotion. If you have two ESXi Servers with the same configuration, the VM will stay on the same pNIC number even after a vMotion. But again, one pNIC may be congested while others are bored. So there is no real load balancing. Route based on IP hash The limitation of the two previously-discussed policies is that a given virtual NIC will always use the same physical network card for all its traffic. IP hash-based load balancing uses the source and destination of the IP address to determine which physical network card to use. Using this algorithm, a VM can communicate through several different physical network cards based on its destination. This option requires configuration of the physical switch's ports to EtherChannel. Because the physical switch is configured similarly, this option is the only one that also provides inbound load distribution, where the distribution is not necessarily balanced. There are some limitations and reasons why this policy is not commonly used. These reasons are described as follows: The route based on IP hash load balancing option involves added complexity and configuration support from upstream switches. Link Aggregation Control Protocol (LACP) or EtherChannel is required for this algorithm to be used. However, this does not apply for a vSphere Standard Switch. For IP hash to be an effective algorithm for load balancing there must be many IP sources and destinations. This is not a common practice for IP storage networks, where a single VMkernel port is used to access a single IP address on a storage device. The same NIC will always send all its traffic to the same destination (for example, Google.com) through the same pNIC, though another destination (for example, bing.com) might go through another pNIC. So, in a nutshell, due to the added complexity, the upstream dependency on the advanced switch configuration and the management overhead, this configuration is rarely used in production environments. The main reason is that if you use IP hash, the pSwitch must be configured with LACP or EtherChannel. Also, if you use LACP or EtherChannel, the load balancing algorithm must be IP hash. This is because with LACP, inbound traffic to the VM could come through either of the pNICs, and the vSwitch must be ready to deliver that to the VM and only IP Hash will do that (the other policies will drop the inbound traffic to this VM that comes in on a pNIC that the VM doesn't use). We have only two failover detection options and those are: Link status only The link status option enables the detection of failures related to the physical network's cables and switch. However, be aware that configuration issues are not detected. This option also cannot detect the link state problems with upstream switches; it works only with the first hop switch from the host. Beacon probing The beacon probing option allows the detection of failures unseen by the link status option, by sending the Ethernet broadcast frames through all the network cards. These network frames authorize the vSwitch to detect faulty configurations or upstream switch failures and force the failover if the ports are blocked. When using an inverted U physical network topology in conjunction with a dual-NIC server, it is recommended to enable link state tracking or a similar network feature in order to avoid traffic black holes. According to VMware's best practices, it is recommended to have at least three cards before activating this functionality. However, if IP hash is going to be used, beacon probing should not be used as a network failure detection, in order to avoid an ambiguous state due to the limitation that a packet cannot hairpin on the port it is received. Beacon probing works by sending out and listening to beacon probes from the NICs in a team. If there are two NICs, then each NIC will send out a probe and the other NICs will receive that probe. Because EtherChannel is considered one link, this will not function properly as the NIC uplinks are not logically separate uplinks. If beacon probing is used, this can result in MAC address flapping errors, and the network connectivity may be interrupted. Designing a network for load balancing and failover for vSphere Distributed Switch The load balancing and failover policies that are chosen for the infrastructure can have an impact on the overall design. Using NIC teaming, we can group several physical network switches attached to a vSwitch. This grouping enables load balancing between the different Physical NICs, and provides fault tolerance if a card failure occurs. The vSphere distributed vSwitch offers a load balancing option that actually takes the network workload into account when choosing the physical uplink. This is route based on a physical NIC load. This is also called Load Based Teaming (LBT). We recommend this load balancing option over the others when using a distributed vSwitch. Benefits of using this load balancing policy are as follows: It is the only load balancing option that actually considers NIC load when choosing uplinks. It does not require upstream switch configuration dependencies like the route based on IP hash algorithm does. When the route based on physical NIC load is combined with the network I/O control, a truly dynamic traffic distribution is achieved. Getting ready To step through this recipe, you will need one or more running ESXi Servers, a vCenter Server, and a working installation of vSphere Client. No other prerequisites are required. How to do it... To change the load balancing policy and select the right one for your environment, and also select the appropriate failover policy you need to follow the proceeding steps: Open up your VMware vSphere Client. Log in to the vCenter Server. Navigate to Networking on the home screen. Navigate to a Distributed Port group and right click and select Edit Settings. Click on the Teaming and Failover section. From the Load Balancing drop-down menu, select Route Based on physical NIC load as the load balancing policy. Choose the appropriate network failover detection policy from the drop-down menu. Click on OK and your settings will be effective. How it works... Load based teaming, also known as route based on physical NIC load, maps vNICs to pNICs and remaps the vNIC to pNIC affiliation if the load exceeds specific thresholds on a pNIC. LBT uses the originating port ID load balancing algorithm for the initial port assignment, which results in the first vNIC being affiliated to the first pNIC, the second vNIC to the second pNIC, and so on. Once the initial placement is over after the VM being powered on, LBT will examine both the inbound and outbound traffic on each of the pNICs and then distribute the load across if there is congestion. LBT will send a congestion alert when the average utilization of a pNIC is 75 percent over a period of 30 seconds. 30 seconds of interval period is being used for avoiding the MAC flapping issues. However, you should enable port fast on the upstream switches if you plan to use STP. VMware recommends LBT over IP hash when you use vSphere Distributed Switch, as it does not require any special or additional settings in the upstream switch layer. In this way you can reduce unnecessary operational complexity. LBT maps vNIC to pNIC and then distributes the load across all the available uplinks, unlike IP hash which just maps the vNIC to pNIC but does not do load distribution. So it may happen that when a high network I/O VM is sending traffic through pNIC0, your other VM will also get to map to the same pNIC and send the traffic. What to know when offloading checksum VMware takes advantage of many of the performance features from modern network adaptors. In this section we are going to talk about two of them and those are: TCP checksum offload TCP segmentation offload Getting ready To step through this recipe, you will need a running ESXi Server and a SSH Client (Putty). No other prerequisites are required. How to do it... The list of network adapter features that are enabled on your NIC can be found in the file /etc/vmware/esx.conf on your ESXi Server. Look for the lines that start with /net/vswitch. However, do not change the default NIC's driver settings unless you have a valid reason to do so. A good practice is to follow any configuration recommendations that are specified by the hardware vendor. Carry out the following steps in order to check the settings: Open up your SSH Client and connect to your ESXi host. Open the file etc/vmware/esx.conf Look for the line that starts with /net/vswitch Your output should look like the following screenshot: How it works... A TCP message must be broken down into Ethernet frames. The size of each frame is the maximum transmission unit (MUT). The default maximum transmission unit is 1500 bytes. The process of breaking messages into frames is called segmentation. Modern NIC adapters have the ability to perform checksum calculations natively. TCP checksums are used to determine the validity of transmitted or received network packets based on error correcting code. These calculations are traditionally performed by the host's CPU. By offloading these calculations to the network adapters, the CPU is freed up to perform other tasks. As a result, the system as a whole runs better. TCP segmentation offload (TSO) allows a TCP/IP stack from the guest OS inside the VM to emit large frames (up to 64KB) even though the MTU of the interface is smaller. Earlier operating system used the CPU to perform segmentation. Modern NICs try to optimize this TCP segmentation by using a larger segment size as well as offloading work from the CPU to the NIC hardware. ESXi utilizes this concept to provide a virtual NIC with TSO support, without requiring specialized network hardware. With TSO, instead of processing many small MTU frames during transmission, the system can send fewer, larger virtual MTU frames. TSO improves performance for the TCP network traffic coming from a virtual machine and for network traffic sent out of the server. TSO is supported at the virtual machine level and in the VMkernel TCP/IP stack. TSO is enabled on the VMkernel interface by default. If TSO becomes disabled for a particular VMkernel interface, the only way to enable TSO is to delete that VMkernel interface and recreate it with TSO enabled. TSO is used in the guest when the VMXNET 2 (or later) network adapter is installed. To enable TSO at the virtual machine level, you must replace the existing VMXNET or flexible virtual network adapter with a VMXNET 2 (or later) adapter. This replacement might result in a change in the MAC address of the virtual network adapter. Selecting the correct virtual network adapter When you configure a virtual machine, you can add NICs and specify the adapter type. The types of network adapters that are available depend on the following factors: The version of the virtual machine, which depends on which host created it or most recently updated it. Whether or not the virtual machine has been updated to the latest version for the current host. The guest operating system. The following virtual NIC types are supported: Vlance VMXNET Flexible E 1000 Enhanced VMXNET (VMXNET 2) VMXNET 3 If you want to know more about these network adapter types then refer to the following KB article: http://kb.vmware.com/kb/1001805 Getting ready To step through this recipe, you will need one or more running ESXi Servers, a vCenter Server, and a working installation of vSphere Client. No other prerequisites are required. How to do it... To choose a particular virtual network adapter you have two ways, one is while you create a new VM and the other one is while adding a new network adaptor to an existing VM. To choose a network adaptor while creating a new VM is as follows: Open vSphere Client. Log in to the vCenter Server. Click on the File menu, and navigate to New| Virtual Machine. Go through the steps and hold on to the step where you need to create network connections. Here you need to choose how many network adaptors you need, which port group you want them to connect to, and an adaptor type. To choose an adaptor type while adding a new network interface in an existing VM you should follow these steps: Open vSphere Client. Log in to the vCenter Server. Navigate to VMs and Templates on your home screen. Select an existing VM where you want to add a new network adaptor, right click and select Edit Settings. Click on the Add button. Select Ethernet Adaptor. Select the Adaptor type and select the network where you want this adaptor to connect. Click on Next and then click on Finish How it works... Among the entire supported virtual network adaptor types, VMXNETis the paravirtualized device driver for virtual networking. The VMXNET driver implements an idealized network interface that passes through the network traffic from the virtual machine to the physical cards with minimal overhead. The three versions of VMXNET are VMXNET, VMXNET 2 (Enhanced VMXNET), and VMXNET 3. The VMXNET driver improves the performance through a number of optimizations as follows: Shares a ring buffer between the virtual machine and the VMkernel, and uses zero copy, which in turn saves CPU cycles. Zero copy improves performance by having the virtual machines and the VMkernel share a buffer, reducing the internal copy operations between buffers to free up CPU cycles. Takes advantage of transmission packet coalescing to reduce address space switching. Batches packets and issues a single interrupt, rather than issuing multiple interrupts. This improves efficiency, but in some cases with slow packet-sending rates, it could hurt throughput while waiting to get enough packets to actually send. Offloads TCP checksum calculation to the network hardware rather than use the CPU resources of the virtual machine monitor. Use vmxnet3 if you can, or the most recent model you can. Use VMware Tools where possible. For certain unusual types of network traffic, sometimes the generally-best model isn't optimal; if you have poor network performance, experiment with other types of vNICs to see which performs best.
Read more
  • 0
  • 0
  • 3698

article-image-developing-wiki-seek-widget-using-javascript
Packt
14 Oct 2009
8 min read
Save for later

Developing Wiki Seek Widget Using Javascript

Packt
14 Oct 2009
8 min read
If you’re searching for details of a particular term in Google, you’re most probably going to see a link for relevant articles from wikipedia.org in the top 10 result list. Wikipedia, is the largest encyclopedia on the Internet, and contains huge collections of articles in many languages. The most significant feature of this encyclopedia is that it is a Wiki, so anybody can contribute to the knowledge base. A Wiki, (a new concept of web2.0), is a collection of web pages whose content can be created and changed by the visitor of the page with simplified mark-up language. Wikis are usually used as knowledge management systems on the web. Brief Introduction to Wikipedia Wikipedia has defined itself as : … a free, multilingual, open content encyclopedia project operated by the United States-based non-profit Wikimedia Foundation. Wikipedia is built upon an open source wiki package called MediaWiki. MediaWiki uses PHP as a server side scripting language and MySql as the database. Wikipedia uses MediaWiki’s wikitext format for editing the text, so the user (without any necessary  knowledge of HTML and CSS) can edit them easily. The Wikitext language (also called Wiki Markup) is a markup language which gives instruction on how outputted text will be displayed. It provides a simplified approach to writing pages in a wiki website. Different types of wiki software employ different styles of Wikitext language. For example, the Wikitext markup language has ways to hyperlink pages within the website but a number of different syntaxes are available for creating such links. Wikipedia was launched by Jimmy Wales and Larry Sanger in 2001 as a means of collecting and summarizing human knowledge in every major language. As of April 2008, Wikipedia had over 10 million articles in 253 languages. With so many articles, it is the largest encyclopedia ever assembled. Wikipedia articles are written collaboratively by volunteers, and any visitor can modify the content of article. Any modification must be accepted by the editors of Wikipedia otherwise the article will be reverted to the previous content. Along with popularity, Wikipedia is also criticized for systematic bias and inconsistency since the modifications must be cleared by the editors. Critics also argue that it’s open nature and the lack of proper sources for many articles makes it unreliable. Searching in Wikipedia To search for a particular article in Wikipedia, you can use the search box in the home page of wikipedia.org.Wikipedia classifies its articles in different sub-domains according to language; “en.wikipedia.org” contains articles in English language whereas “es.wikipedia.org” contains Spanish articles. Whenever you select “english” language in the dropdown box, the related articles will be searched over “en.wikipedia.org” and so on for the another language. You can also search the articles of Wikipedia from a remote server. For this, you have to send the language and search parameters to http://www.wikipedia.org/search-redirect.php via the GET method Creating a Wiki Seek Widget Up till now, we’ve looked at the background concept of Wikipedia. Now, let’s start building the widget. This widget contains a form with three components. A textbox where the visitors enters the search keyword, a dropdown list which contains the language of the article and finally a submit button to search the articles of Wikipedia. By the time we’re done, you should have a widget that looks like this: Concept for creating form Before looking at the JavaScript code, first let’s understand the architecture of the form with the parameters to be sent for searching Wikipedia. The request should be sent to http://www.wikipedia.org/search-redirect.php via the GET method. <form action="http://www.wikipedia.org/search-redirect.php" ></form> If you don’t specify the method attribute in the form, the form uses GET, which is the default method. After creating the form element, we need to add the textbox inside the above form with the name search because we’ve to send the search keyword in the name of search parameter. <input type="text" name="search" size="20" /> After adding the textbox for the search keyword, we need to add the dropdown list which contains the language of the article to search. The name of this dropdown-list should be language as we’ve to send the language code to the above URL in the language parameter. These language codes are two or three letter codes specified by ISO. ISO has assigned three letter language codes for most of the popular languages of the world. And, there are a few languages that are represented by two letter ISO codes. For example, eng and en are the three and two letter language code for English. Some of the article languages of Wikipedia don’t have ISO codes, and you have to find the value of the language parameter from Wikipedia. For example, articles in the Alemannisch language is als. Here is the HTML code for constructing a dropdown list in major languages : <select name="language"><option value="de" >Deutsch</option><option value="en" selected="selected">English</option><option value="es" >Español</option><option value="eo" >Esperanto</option><option value="fr" >Français</option><option value="it" >Italiano</option><option value="hu" >Magyar</option><option value="nl" >Nederlands</option></select> As you can see in the above dropdown list, English is the default language selected. Now, we just need to add a submit button in the above form to complete the form for searching the article in wikipedia. <input type="submit" name="go" value="Search" title="Search in wikipedia" /> Put all the HTML code together to create the form. JavaScript Code As we’ve already got the background concept of the HTML form, we just have to use the document.write() to output the HTML to the web browser. Here is the JavaScript code to create the Wiki Seek Widget : document.write('<div>');document.write('<form action="http://www.wikipedia.org/search-redirect.php" >');document.write('<input type="text" name="search" size="20" />');document.write('&nbsp;<select name="language">');document.write('<option value="de" >Deutsch</option>');document.write('<option value="en" selected="selected">English</option>');document.write('<option value="es" >Español</option>');document.write('<option value="eo" >Esperanto</option>');document.write('<option value="fr" >Français</option>');document.write('<option value="it" >Italiano</option>');document.write('<option value="hu" >Magyar</option>');document.write('<option value="nl" >Nederlands</option>');document.write('</select>');document.write('&nbsp;<input type="submit" name="go" value="Search" title="Search in wikipedia" />');document.write('</form>');document.write('</div>'); In the above code, I’ve used division (div) as the container for the HTML form. I’ve also saved the above code in a wiki_seek.js file. The above JavaScript code displays a non-stylish widget. To make a stylish widget, you can use style property in the input elements of the form. Using Wiki Seek widget To use this wiki seek widget we’ve to follow these steps: First of all, we need to upload the above wiki_seek.js to a web server so that it can be used by the client websites. Let’s suppose that is uploaded and placed in the URL : http://www.widget-server.com/wiki_seek.js Now, we can widget in any web pages by placing the following JavaScript Code in the website. <script type="text/javascript" language="javascript"src="http://www.widget-server.com/wiki_seek.js"></script> The Wiki Seek widget is displayed in any part of web page, where you place the above code.
Read more
  • 0
  • 0
  • 3687

article-image-creating-pop-menu
Packt
14 Jun 2013
7 min read
Save for later

Creating a pop-up menu

Packt
14 Jun 2013
7 min read
(For more resources related to this topic, see here.) How to do it... Open the application model (Application.e4xmi) and go to Application | Windows | Trimmed Window | Controls | Perspective Stack | Perspective | Controls | PartSashContainer | Part ( Code Snippets). Expand the Code Snippet part and right-click on the Menus node. Select Add child | Popup Menu. Set the ID of the pop-up menu to codesnippetapp.snippetlist.popupmenu. Right-click on the newly added pop-up menu and select Add Child | DirectMenuItem. Set Label of the menu item as New Snippet. Click on Class URI link. This opens the New Handler wizard. Click on the Browse button next to the Package textbox and select codesnippetapp.handlers from the list of packages displayed. Set Name as NewSnippetMenuHandler and click on the Finish button. The new class file is opened in the editor. Go back to the application model. Refer to the following screenshot: Right-click on the Popup Menu node and add another pop-up menu item with the Delete label and the DeleteSnippetMenuHandler class. Now we need to register this pop-up menu with the TableViewer class in the Code Snippets part. Open the class SnippetListView (you can find this class in the codesnippetapp.views package). We will have to register the pop-up menu using Menu Service. Add the EMenuService argument to the postConstruct method: @PostConstruct public void postConstruct(Composite parent, IEclipseContext ctx, EMenuService menuService) Append the following code to the postConstruct method: menuService.registerContextMenu(snippetsList.getTable(), "codesnippetapp.snippetlist.popupmenu"); Run the application. Right-click in the TableViewer class on the left-hand side. You should see a pop-up menu with two options: New Snippet and Delete. How it works... To add a pop-up menu, you first need to create a menu in the application model for a part in which you want to display the menu. In this recipe, we added a menu to the Code Snippets part. Then, you add menu items. In this recipe, we added two DirectMenuItem. For the main menu bar in the task of adding menu and toolbar buttons, we added HandledMenuItem, because we wanted to share the handler for the menu between toolbar button and menu item. However, in this case, we need only one implementation of options in the pop-up menu, so we created DirectMenuItem. But, if you want to add keyboard shortcuts for the menu options, then you may want to create HandledMenuItem instead of DirectMenuItem. For each menu item, you set a class URI that is a handler class for the menu item. The next step is to register this pop-up menu with a UI control. In our application, we want to associate this menu with the TableViewer class that displays a list of snippets. To register a menu with any UI control, you need to get an instance of EMenuService. We obtained this instance in the postConstruct method of SnippetListView using DI—we added the EMenuService argument to the postConstruct method. Then, we used registerContextMenu of EMenuService to associate the pop-up menu with the TableViewer class. registerContextMenu takes instances of the UI control and menu ID as arguments. There's more... The Delete option in our pop-up menu makes sense only when you click on any snippet. So, when you right-click on an area of TreeViewer that does not have any snippet at that location, the Delete option should not be displayed, only the New Snippet option. This can be done using core expressions. You can find more information about core expressions at http://wiki.eclipse.org/Platform_Expression_Framework, and http://wiki.eclipse.org/Command_Core_Expressions. We will use a core expression to decide if the Delete menu option should be displayed. We will add a mouse listener to the TableViewer class. If the mouse was clicked on a Snippet, then we will add SnippetData to IEclipseContext with the snippet_at_mouse_click key. If there is no snippet at the location, then we will remove this key from IEclipseContext. Then, we will add a core expression to check if the snippet_at_mouse_click variable is of type codesnippetapp.data.SnippetData. We will then associate this core expression with the Delete menu item in the application model. Adding mouse listener to the TableViewer class Create a static field in the SnippetListView class. private static String SNIPPET_AT_MOUSE_CLICK = "snippet_at_mouse_ click"; Make the ctx argument of the postConstruct method, final. Append the following code in the postConstruct method: //Add mouse listener to check if there is a snippet at mouse click snippetsList.getTable().addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { if (e.button == 1) //Ignore if left mouse button return; //Get snippet at the location of mouse click TableItem itemAtClick = snippetsList.getTable(). getItem(new Point(e.x, e.y)); if (itemAtClick != null) { //Add selected snippet to the context ctx.set(SNIPPET_AT_MOUSE_CLICK, itemAtClick.getData()); } else { //No snippet at the mouse click. Remove the variable ctx.remove(SNIPPET_AT_MOUSE_CLICK); } } }); Creating core expression Carry out to the following steps: Open plugin.xml and go to the Dependencies tab. Add org.eclipse.core.expression as a required plugin. Go to the Extensions tab. Add the org.eclipse.core.expressions. definitions extension. This will add a new definition. Change the ID of the definition to CodeSnippetApp.delete.snippet.expression. Right-click on the definition and select New |With. Change the name of the variable to snippet_at_mouse_click. This is the same variable name we set in the SnippetListView class. Right-click on the With node, and select New | instanceof option. Set the value to codesnippetapp.data.SnippetData. This core expression will be true when the type of (instanceof) the snippet_at_mouse_click variable is codesnippetapp.data.SnippetData. Click on plugin.xml and verify that the core expression definition is as follows: <extension point="org.eclipse.core.expressions.definitions"> <definition id="CodeSnippetApp.delete.snippet.expression"> <with variable="snippet_at_mouse_click"> <instanceof value="codesnippetapp.data.SnippetData"> </instanceof> </with> </definition> </extension> Setting the core expression for Menu Item Open the application model (Application.e4xmi) and go to DirectMenuItem for the Delete pop-up menu. Right-click on the menu item and select Add child | VisibleWhen Core Expression. This will add a Core Expression child node. Click on the Core Expression node and then on the Find button next to the Expression Id textbox and select CodeSnippetApp.delete.snippet. expression from the list. This is the ID of the core expression definition we added in plugin.xml. Run the application. When you right-click on the Snippets List view, which does not have any snippet at this point, you should see only the New Snippet menu option. Summary In this task, we created a pop-up menu that is displayed when you right-click in the snippets list. If no snippet is selected at a location where you right-click, then it displays a pop-up menu with a single option to add a snippet. If there is a snippet at the location, then we display a menu that has options to delete the snippet and add a snippet. Resources for Article : Further resources on this subject: Installing Alfresco Software Development Kit (SDK) [Article] JBoss AS plug-in and the Eclipse Web Tools Platform [Article] Deployment of Reports with BIRT [Article]
Read more
  • 0
  • 0
  • 3680

article-image-classification-and-regression-trees
Packt
02 Aug 2013
23 min read
Save for later

Classification and Regression Trees

Packt
02 Aug 2013
23 min read
(For more resources related to this topic, see here.) Recursive partitions The name of the library package rpart, shipped along with R, stands for Recursive Partitioning . The package was first created by Terry M Therneau and Beth Atkinson , and is currently maintained by Brian Ripley . We will first have a peek at means recursive partitions are. A complex and contrived relationship is generally not identifiable by linear models. In the previous chapter, we saw the extensions of the linear models in piecewise, polynomial, and spline regression models. It is also well known that if the order of a model is larger than 4, then interpretation and usability of the model becomes more difficult. We consider a hypothetical dataset, where we have two classes for the output Y and two explanatory variables in X1 and X2. The two classes are indicated by filled-in green circles and red squares. First, we will focus only on the left display of Figure 1: A complex classification dataset with partitions , as it is the actual depiction of the data. At the outset, it is clear that a linear model is not appropriate, as there is quite an overlap of the green and red indicators. Now, there is a clear demarcation of the classification problem accordingly, as X1 is greater than 6 or not. In the area on the left side of X1=6, the mid-third region contains a majority of green circles and the rest are red squares. The red squares are predominantly identifiable accordingly, as the X2 values are either lesser than or equal to 3 or greater than 6. The green circles are the majority values in the region of X2 being greater than 3 and lesser than 6. A similar story can be built for the points on the right side of X1 greater than 6. Here, we first partitioned the data according to X1 values first, and then in each of the partitioned region, we obtained partitions according to X2 values. This is the act of recursive partitioning. Figure 1: A complex classification dataset with partitions Let us obtain the preceding plot in R. Time for action – partitioning the display plot We first visualize the CART_Dummy dataset and then look in the next subsection at how CART gets the patterns, which are believed to exist in the data. Obtain the dataset CART_Dummy from the RSADBE package by using data( CART_Dummy). Convert the binary output Y as a factor variable, and attach the data frame with CART_Dummy$Y <- as.factor(CART_Dummy$Y). attach(CART_Dummy) In Figure 1: A complex classification dataset with partitions , the red squares refer to 0 and the green circles to 1. Initialize the graphics windows for the three samples by using par(mfrow= c(1,2)). Create a blank scatter plot: plot(c(0,12),c(0,10),type="n",xlab="X1",ylab="X2"). Plot the green circles and red squares: points(X1[Y==0],X2[Y==0],pch=15,col="red") points(X1[Y==1],X2[Y==1],pch=19,col="green") title(main="A Difficult Classification Problem") Repeat the previous two steps to obtain the identical plot on the right side of the graphics window. First, partition according to X1 values by using abline(v=6,lwd=2). Add segments on the graph with the segment function: segments(x0=c(0,0,6,6),y0=c(3.75,6.25,2.25,5),x1=c(6,6,12,12),y1=c(3.75,6.25,2.25,5),lwd=2) title(main="Looks a Solvable Problem Under Partitions") What just happened? A complex problem is simplified through partitioning! A more generic function, segments, has nicely slipped in our program, which you may use for many other scenarios. Now, this approach of recursive partitioning is not feasible all the time! Why? We seldom deal with two or three explanatory variables and data points as low as in the preceding hypothetical example. The question is how one creates recursive partitioning of the dataset. Breiman, et. al. (1984) and Quinlan (1988) have invented tree building algorithms, and we will follow the Breiman, et. al. approach in the rest of book. The CART discussion in this book is heavily influenced by Berk (2008). Splitting the data In the earlier discussion, we saw that partitioning the dataset can benefit a lot in reducing the noise in the data. The question is how does one begin with it? The explanatory variables can be discrete or continuous. We will begin with the continuous (numeric objects in R) variables. For a continuous variable, the task is a bit simpler. First, identify the unique distinct values of the numeric object. Let us say, for example, that the distinct values of a numeric object, say height in cms, are 160, 165, 170, 175, and 180. The data partitions are then obtained as follows: data[Height<=160,], data[Height>160,] data[Height<=165,], data[Height>165,] data[Height<=170,], data[Height>170,] data[Height<=175,], data[Height>175,] The reader should try to understand the rationale behind the code, and certainly this is just an indicative one. Now, we consider the discrete variables. Here, we have two types of variables, namely categorical and ordinal . In the case of ordinal variables, we have an order among the distinct values. For example, in the case of the economic status variable, the order may be among the classes Very Poor, Poor, Average, Rich, and Very Rich. Here, the splits are similar to the case of continuous variable, and if there are m distinct orders, we consider m -1 distinct splits of the overall data. In the case of a categorical variable with m categories, for example the departments A to F of the UCBAdmissions dataset, the number of possible splits becomes 2m-1-1. However, the benefit of using software like R is that we do not have to worry about these issues. The first tree In the CART_Dummy dataset, we can easily visualize the partitions for Y as a function of the inputs X1 and X2. Obviously, we have a classification problem, and hence we will build the classification tree. Time for action – building our first tree The rpart function from the library rpart will be used to obtain the first classification tree. The tree will be visualized by using the plot options of rpart, and we will follow this up with extracting the rules of a tree by using the asRules function from the rattle package. Load the rpart package by using library(rpart). Create the classification tree with CART_Dummy_rpart <- rpart(Y~ X1+X2,data=CART_Dummy). Visualize the tree with appropriate text labels by using plot(CART_Dummy_rpart); text(CART_Dummy_rpart). Figure 2: A classification tree for the dummy dataset Now, the classification tree flows as follows. Obviously, the tree using the rpart function does not partition as simply as we did in Figure 1: A complex classification dataset with partitions , the working of which will be dealt within the third section of this chapter. First, we check if the value of the second variable X2 is less than 4.875. If the answer is an affirmation, we move to the left side of the tree; the right side in the other case. Let us move to the right side. A second question asked is whether X1 is lesser than 4.5 or not, and then if the answer is yes it is identified as a red square, and otherwise a green circle. You are now asked to interpret the left side of the first node. Let us look at the summary of CART_Dummy_rpart. Apply the summary, an S3 method, for the classification tree with summary( CART_Dummy_rpart). That one is a lot of output! Figure 3: Summary of a classification tree Our interests are in the nodes numbered 5 to 9! Why? The terminal nodes, of course! A terminal node is one in which we can't split the data any further, and for the classification problem, we arrive at a class assignment as the class that has a majority count at the node. The summary shows that there are indeed some misclassifications too. Now, wouldn't it be great if R gave the terminal nodes asRules. The function asRules from the rattle package extracts the rules from an rpart object. Let's do it! Invoke the rattle package library(rattle) and using the asRules function, extract the rules from the terminal nodes with asRules(CART_Dummy_rpart). The result is the following set of rules: Figure 4: Extracting "rules" from a tree! We can see that the classification tree is not according to our "eye-bird" partitioning. However, as a final aspect of our initial understanding, let us plot the segments using the naïve way. That is, we will partition the data display according to the terminal nodes of the CART_Dummy_rpart tree. The R code is given right away, though you should make an effort to find the logic behind it. Of course, it is very likely that by now you need to run some of the earlier code that was given previously. abline(h=4.875,lwd=2) segments(x0=4.5,y0=4.875,x1=4.5,y1=10,lwd=2) abline(h=1.75,lwd=2) segments(x0=3.5,y0=1.75,x1=3.5,y1=4.875,lwd=2) title(main="Classification Tree on the Data Display") It can be easily seen from the following that rpart works really well: Figure 5: The terminal nodes on the original display of the data What just happened? We obtained our first classification tree, which is a good thing. Given the actual data display, the classification tree gives satisfactory answers. We have understood the "how" part of a classification tree. The "why" aspect is very vital in science, and the next section explains the science behind the construction of a regression tree, and it will be followed later by a detailed explanation of the working of a classification tree. The construction of a regression tree In the CART_Dummy dataset, the output is a categorical variable, and we built a classification tree for it. The same distinction is required in CART, and we thus build classification trees for binary random variables, where regression trees are for continuous random variables. Recall the rationale behind the estimation of regression coefficients for the linear regression model. The main goal was to find the estimates of the regression coefficients, which minimize the error sum of squares between the actual regressand values and the fitted values. A similar approach is followed here, in the sense that we need to split the data at the points that keep the residual sum of squares to a minimum. That is, for each unique value of a predictor, which is a candidate for the node value, we find the sum of squares of y's within each partition of the data, and then add them up. This step is performed for each unique value of the predictor, and the value, which leads to the least sum of squares among all the candidates, is selected as the best split point for that predictor. In the next step, we find the best split points for each of the predictors, and then the best split is selected across the best split points across the predictors. Easy! Now, the data is partitioned into two parts according to the best split. The process of finding the best split within each partition is repeated in the same spirit as for the first split. This process is carried out in a recursive fashion until the data can't be partitioned any further. What is happening here? The residual sum of squares at each child node will be lesser than that in the parent node. At the outset, we record that the rpart function does the exact same thing. However, as a part of cleaner understanding of the regression tree, we will write raw R codes and ensure that there is no ambiguity in the process of understanding CART. We will begin with a simple example of a regression tree, and use the rpart function to plot the regression function. Then, we will first define a function, which will extract the best split given by the covariate and dependent variable. This action will be repeated for all the available covariates, and then we find the best overall split. This will be verified with the regression tree. The data will then be partitioned by using the best overall split, and then the best split will be identified for each of the partitioned data. The process will be repeated until we reach the end of the complete regression tree given by the rpart. First, the experiment! The cpus dataset available in the MASS package contains the relative performance measure of 209 CPUs in the perf variable. It is known that the performance of a CPU depends on factors such as the cycle time in nanoseconds (syct), minimum and maximum main memory in kilobytes (mmin and mmax), cache size in kilobytes (cach), and minimum and maximum number of channels (chmin and chmax). The task in hand is to model the perf as a function of syct, mmin, mmax, cach, chmin, and chmax. The histogram of perf—try hist(cpus$perf)—will show a highly skewed distribution, and hence we will build a regression tree for the logarithm transformation log10(perf). Time for action – the construction of a regression tree A regression tree is first built by using the rpart function. The getNode function is introduced, which helps in identifying the split node at each stage, and using it we build a regression tree and verify that we had the same tree as returned by the rpart function. Load the MASS library by using library(MASS). Create the regression tree for the logarithm (to the base 10) of perf as a function of the covariates explained earlier, and display the regression tree: cpus.ltrpart <- rpart(log10(perf)~syct+mmin+mmax+cach+chmin+chmax, data=cpus) plot(cpus.ltrpart); text(cpus.ltrpart) The regression tree will be indicated as follows: Figure 6: Regression tree for the "perf" of a CPU We will now define the getNode function. Given the regressand and the covariate, we need to find the best split in the sense of the sum of squares criterion. The evaluation needs to be done for every distinct value of the covariate. If there are m distinct points, we need m -1 evaluations. At each distinct point, the regressand needs to be partitioned accordingly, and the sum of squares should be obtained for each partition. The two sums of squares (in each part) are then added to obtain the reduced sum of squares. Thus, we create the required function to meet all these requirements. Create the getNode function in R by running the following code: getNode <- function(x,y) { xu <- sort(unique(x),decreasing=TRUE) ss <- numeric(length(xu)-1) for(i in 1:length(ss)) { partR <- y[x>xu[i]] partL <- y[x<=xu[i]] partRSS <- sum((partR-mean(partR))^2) partLSS <- sum((partL-mean(partL))^2) ss[i]<-partRSS + partLSS } return(list(xnode=xu[which(ss==min(ss,na.rm=TRUE))], minss = min(ss,na.rm=TRUE),ss,xu)) } The getNode function gives the best split for a given covariate. It returns a list consisting of four objects: xnode, which is a datum of the covariate x that gives the minimum residual sum of squares for the regressand y The value of the minimum residual sum of squares The vector of the residual sum of squares for the distinct points of the vector x The vector of the distinct x values We will run this function for each of the six covariates, and find the best overall split. The argument na.rm=TRUE is required, as at the maximum value of x we won't get a numeric value. We will first execute the getNode function on the syct covariate, and look at the output we get as a result: > getNode(cpus$syct,log10(cpus$perf))$xnode [1] 48 > getNode(cpus$syct,log10(cpus$perf))$minss [1] 24.72 > getNode(cpus$syct,log10(cpus$perf))[[3]] [1] 43.12 42.42 41.23 39.93 39.44 37.54 37.23 36.87 36.51 36.52 35.92 34.91 [13] 34.96 35.10 35.03 33.65 33.28 33.49 33.23 32.75 32.96 31.59 31.26 30.86 [25] 30.83 30.62 29.85 30.90 31.15 31.51 31.40 31.50 31.23 30.41 30.55 28.98 [37] 27.68 27.55 27.44 26.80 25.98 27.45 28.05 28.11 28.66 29.11 29.81 30.67 [49] 28.22 28.50 24.72 25.22 26.37 28.28 29.10 33.02 34.39 39.05 39.29 > getNode(cpus$syct,log10(cpus$perf))[[4]] [1] 1500 1100 900 810 800 700 600 480 400 350 330 320 300 250 240 [16] 225 220 203 200 185 180 175 167 160 150 143 140 133 125 124 [31] 116 115 112 110 105 100 98 92 90 84 75 72 70 64 60 [46] 59 57 56 52 50 48 40 38 35 30 29 26 25 23 17 The least sum of squares at a split for the best split value of the syct variable is 24.72, and it occurs at a value of syct greater than 48. The third and fourth list objects given by getNode, respectively, contain the details of the sum of squares for the potential candidates and the unique values of syct. The values of interest are highlighted. Thus, we will first look at the second object from the list output for all the six covariates to find the best split among the best split of each of the variables, by the residual sum of squares criteria. Now, run the getNode function for the remaining five covariates: getNode(cpus$syct,log10(cpus$perf))[[2]] getNode(cpus$mmin,log10(cpus$perf))[[2]] getNode(cpus$mmax,log10(cpus$perf))[[2]] getNode(cpus$cach,log10(cpus$perf))[[2]] getNode(cpus$chmin,log10(cpus$perf))[[2]] getNode(cpus$chmax,log10(cpus$perf))[[2]] getNode(cpus$cach,log10(cpus$perf))[[1]] sort(getNode(cpus$cach,log10(cpus$perf))[[4]],decreasing=FALSE) The output is as follows: Figure 7: Obtaining the best "first split" of regression tree The sum of squares for cach is the lowest, and hence we need to find the best split associated with it, which is 24. However, the regression tree shows that the best split is for the cach value of 27. The getNode function says that the best split occurs at a point greater than 24, and hence we take the average of 24 and the next unique point at 30. Having obtained the best overall split, we next obtain the first partition of the dataset. Partition the data by using the best overall split point: cpus_FS_R <- cpus[cpus$cach>=27,] cpus_FS_L <- cpus[cpus$cach<27,] The new names of the data objects are clear with _FS_R indicating the dataset obtained on the right side for the first split, and _FS_L indicating the left side. In the rest of the section, the nomenclature won't be further explained. Identify the best split in each of the partitioned datasets: getNode(cpus_FS_R$syct,log10(cpus_FS_R$perf))[[2]] getNode(cpus_FS_R$mmin,log10(cpus_FS_R$perf))[[2]] getNode(cpus_FS_R$mmax,log10(cpus_FS_R$perf))[[2]] getNode(cpus_FS_R$cach,log10(cpus_FS_R$perf))[[2]] getNode(cpus_FS_R$chmin,log10(cpus_FS_R$perf))[[2]] getNode(cpus_FS_R$chmax,log10(cpus_FS_R$perf))[[2]] getNode(cpus_FS_R$mmax,log10(cpus_FS_R$perf))[[1]] sort(getNode(cpus_FS_R$mmax,log10(cpus_FS_R$perf))[[4]], decreasing=FALSE) getNode(cpus_FS_L$syct,log10(cpus_FS_L$perf))[[2]] getNode(cpus_FS_L$mmin,log10(cpus_FS_L$perf))[[2]] getNode(cpus_FS_L$mmax,log10(cpus_FS_L$perf))[[2]] getNode(cpus_FS_L$cach,log10(cpus_FS_L$perf))[[2]] getNode(cpus_FS_L$chmin,log10(cpus_FS_L$perf))[[2]] getNode(cpus_FS_L$chmax,log10(cpus_FS_L$perf))[[2]] getNode(cpus_FS_L$mmax,log10(cpus_FS_L$perf))[[1]] sort(getNode(cpus_FS_L$mmax,log10(cpus_FS_L$perf))[[4]], decreasing=FALSE) The following screenshot gives the results of running the preceding R code: Figure 8: Obtaining the next two splits Thus, for the first right partitioned data, the best split is for the mmax value as the mid-point between 24000 and 32000; that is, at mmax = 28000. Similarly, for the first left-partitioned data, the best split is the average value of 6000 and 6200, which is 6100, for the same mmax covariate. Note the important step here. Even though we used cach as the criteria for the first partition, it is still used with the two partitioned data. The results are consistent with the display given by the regression tree, Figure 6: Regression tree for the "perf" of a CPU . The next R program will take care of the entire first split's right side's future partitions. Partition the first right part cpus_FS_R as follows: cpus_FS_R_SS_R <- cpus_FS_R[cpus_FS_R$mmax>=28000,] cpus_FS_R_SS_L <- cpus_FS_R[cpus_FS_R$mmax<28000,] Obtain the best split for cpus_FS_R_SS_R and cpus_FS_R_SS_L by running the following code: cpus_FS_R_SS_R <- cpus_FS_R[cpus_FS_R$mmax>=28000,] cpus_FS_R_SS_L <- cpus_FS_R[cpus_FS_R$mmax<28000,] getNode(cpus_FS_R_SS_R$syct,log10(cpus_FS_R_SS_R$perf))[[2]] getNode(cpus_FS_R_SS_R$mmin,log10(cpus_FS_R_SS_R$perf))[[2]] getNode(cpus_FS_R_SS_R$mmax,log10(cpus_FS_R_SS_R$perf))[[2]] getNode(cpus_FS_R_SS_R$cach,log10(cpus_FS_R_SS_R$perf))[[2]] getNode(cpus_FS_R_SS_R$chmin,log10(cpus_FS_R_SS_R$perf))[[2]] getNode(cpus_FS_R_SS_R$chmax,log10(cpus_FS_R_SS_R$perf))[[2]] getNode(cpus_FS_R_SS_R$cach,log10(cpus_FS_R_SS_R$perf))[[1]] sort(getNode(cpus_FS_R_SS_R$cach,log10(cpus_FS_R_SS_R$perf))[[4]], decreasing=FALSE) getNode(cpus_FS_R_SS_L$syct,log10(cpus_FS_R_SS_L$perf))[[2]] getNode(cpus_FS_R_SS_L$mmin,log10(cpus_FS_R_SS_L$perf))[[2]] getNode(cpus_FS_R_SS_L$mmax,log10(cpus_FS_R_SS_L$perf))[[2]] getNode(cpus_FS_R_SS_L$cach,log10(cpus_FS_R_SS_L$perf))[[2]] getNode(cpus_FS_R_SS_L$chmin,log10(cpus_FS_R_SS_L$perf))[[2]] getNode(cpus_FS_R_SS_L$chmax,log10(cpus_FS_R_SS_L$perf))[[2]] getNode(cpus_FS_R_SS_L$cach,log10(cpus_FS_R_SS_L$perf))[[1]] sort(getNode(cpus_FS_R_SS_L$cach,log10(cpus_FS_R_SS_L$perf))[[4]],decreasing=FALSE) For the cpus_FS_R_SS_R part, the final division is according to cach being greater than 56 or not (average of 48 and 64). If the cach value in this partition is greater than 56, then perf (actually log10(perf)) ends in the terminal leaf 3, else 2. However, for the region cpus_FS_R_SS_L, we partition the data further by the cach value being greater than 96.5 (average of 65 and 128). In the right side of the region, log10(perf) is found as 2, and a third level split is required for cpus_FS_R_SS_L with cpus_FS_R_SS_L_TS_L. Note that though the final terminal leaves of the cpus_FS_R_SS_L_TS_L region shows the same 2 as the final log10(perf), this may actually result in a significant variability reduction of the difference between the predicted and the actual log10(perf) values. We will now focus on the first main split's left side. Figure 9: Partitioning the right partition after the first main split Partition cpus_FS_L accordingly, as the mmax value being greater than 6100 or otherwise: cpus_FS_L_SS_R <- cpus_FS_L[cpus_FS_L$mmax>=6100,] cpus_FS_L_SS_L <- cpus_FS_L[cpus_FS_L$mmax<6100,] The rest of the partition for cpus_FS_L is completely given next. The details will be skipped and the R program is given right away: cpus_FS_L_SS_R <- cpus_FS_L[cpus_FS_L$mmax>=6100,] cpus_FS_L_SS_L <- cpus_FS_L[cpus_FS_L$mmax<6100,] getNode(cpus_FS_L_SS_R$syct,log10(cpus_FS_L_SS_R$perf))[[2]] getNode(cpus_FS_L_SS_R$mmin,log10(cpus_FS_L_SS_R$perf))[[2]] getNode(cpus_FS_L_SS_R$mmax,log10(cpus_FS_L_SS_R$perf))[[2]] getNode(cpus_FS_L_SS_R$cach,log10(cpus_FS_L_SS_R$perf))[[2]] getNode(cpus_FS_L_SS_R$chmin,log10(cpus_FS_L_SS_R$perf))[[2]] getNode(cpus_FS_L_SS_R$chmax,log10(cpus_FS_L_SS_R$perf))[[2]] getNode(cpus_FS_L_SS_R$syct,log10(cpus_FS_L_SS_R$perf))[[1]] sort(getNode(cpus_FS_L_SS_R$syct,log10(cpus_FS_L_SS_R$perf))[[4]], decreasing=FALSE) getNode(cpus_FS_L_SS_L$syct,log10(cpus_FS_L_SS_L$perf))[[2]] getNode(cpus_FS_L_SS_L$mmin,log10(cpus_FS_L_SS_L$perf))[[2]] getNode(cpus_FS_L_SS_L$mmax,log10(cpus_FS_L_SS_L$perf))[[2]] getNode(cpus_FS_L_SS_L$cach,log10(cpus_FS_L_SS_L$perf))[[2]] getNode(cpus_FS_L_SS_L$chmin,log10(cpus_FS_L_SS_L$perf))[[2]] getNode(cpus_FS_L_SS_L$chmax,log10(cpus_FS_L_SS_L$perf))[[2]] getNode(cpus_FS_L_SS_L$mmax,log10(cpus_FS_L_SS_L$perf))[[1]] sort(getNode(cpus_FS_L_SS_L$mmax,log10(cpus_FS_L_SS_L$perf))[[4]],decreasing=FALSE) cpus_FS_L_SS_R_TS_R <- cpus_FS_L_SS_R[cpus_FS_L_SS_R$syct<360,] getNode(cpus_FS_L_SS_R_TS_R$syct,log10(cpus_FS_L_SS_R_TS_R$ perf))[[2]] getNode(cpus_FS_L_SS_R_TS_R$mmin,log10(cpus_FS_L_SS_R_TS_R$ perf))[[2]] getNode(cpus_FS_L_SS_R_TS_R$mmax,log10(cpus_FS_L_SS_R_TS_R$ perf))[[2]] getNode(cpus_FS_L_SS_R_TS_R$cach,log10(cpus_FS_L_SS_R_TS_R$ perf))[[2]] getNode(cpus_FS_L_SS_R_TS_R$chmin,log10(cpus_FS_L_SS_R_TS_R$ perf))[[2]] getNode(cpus_FS_L_SS_R_TS_R$chmax,log10(cpus_FS_L_SS_R_TS_R$ perf))[[2]] getNode(cpus_FS_L_SS_R_TS_R$chmin,log10(cpus_FS_L_SS_R_TS_R$ perf))[[1]] sort(getNode(cpus_FS_L_SS_R_TS_R$chmin,log10(cpus_FS_L_SS_R_TS_R$perf))[[4]],decreasing=FALSE) We will now see how the : Figure 10: Partitioning the left partition after the first main split We leave it to you to interpret the output arising from the previous action. What just happened? Using the rpart function from the rpart library we first built the regression tree for log10(perf). Then, we explored the basic definitions underlying the construction of a regression tree and defined the getNode function to obtain the best split for a pair of regressands and a covariate. This function is then applied for all the covariates, and the best overall split is obtained; using this we get our first partition of the data, which will be in agreement with the tree given by the rpart function. We then recursively partitioned the data by using the getNode function and verified that all the best splits in each partitioned data are in agreement with the one provided by the rpart function. The reader may wonder if the preceding tedious task was really essential. However, it has been the experience of the author that users/readers seldom remember the rationale behind using direct code/functions for any software after some time. Moreover, CART is a difficult concept and it is imperative that we clearly understand our first tree, and return to the preceding program whenever the understanding of a science behind CART is forgotten. Summary We began with the idea of recursive partitioning and gave a legitimate reason as to why such an approach is practical. The CART technique is completely demystified by using the getNode function, which has been defined appropriately depending upon whether we require a regression or a classification tree. Resources for Article : Further resources on this subject: Organizing, Clarifying and Communicating the R Data Analyses [Article] Graphical Capabilities of R [Article] Customizing Graphics and Creating a Bar Chart and Scatterplot in R [Article]
Read more
  • 0
  • 0
  • 3675

article-image-eventbus-class
Packt
23 Sep 2013
14 min read
Save for later

The EventBus Class

Packt
23 Sep 2013
14 min read
(For more resources related to this topic, see here.) When developing software, the idea of objects sharing information or collaborating with each other is a must. The difficulty lies in ensuring that communication between objects is done effectively, but not at the cost of having highly coupled components. Objects are considered highly coupled when they have too much detail about other components' responsibilities. When we have high coupling in an application, maintenance becomes very challenging, as any change can have a rippling effect. To help us cope with this software design issue; we have event-based programming. In event-based programming, objects can either subscribe/listen for specific events, or publish events to be consumed. In Java, we have had the idea of event listeners for some time. An event listener is an object whose purpose is to be notified when a specific event occurs. In this article, we are going to discuss the Guava EventBus class and how it facilitates the publishing and subscribing of events. The EventBus class will allow us to achieve the level of collaboration we desire, while doing so in a manner that results in virtually no coupling between objects. It's worth noting that the EventBus is a lightweight, in-process publish/subscribe style of communication, and is not meant for inter-process communication. We are going to cover several classes in this article that have an @Beta annotation indicating that the functionality of the class may be subject to change in future releases of Guava. EventBus The EventBus class (found in the com.google.common.eventbus package) is the focal point for establishing the publish/subscribe-programming paradigm with Guava. At a very high level, subscribers will register with EventBus to be notified of particular events, and publishers will send events to EventBus for distribution to interested subscribers. All the subscribers are notified serially, so it's important that any code performed in the event-handling method executes quickly. Creating an EventBus instance Creating an EventBus instance is accomplished by merely making a call to the EventBus constructor: EventBus eventBus = new EventBus(); We could also provide an optional string argument to create an identifier (for logging purposes) for EventBus: EventBus eventBus = new EventBus(TradeAccountEvent.class.getName()); Subscribing to events The following three steps are required by an object to receive notifications from EventBus,: The object needs to define a public method that accepts only one argument. The argument should be of the event type for which the object is interested in receiving notifications. The method exposed for an event notification is annotated with an @Subscribe annotation. Finally, the object registers with an instance of EventBus, passing itself as an argument to the EventBus.register method. Posting the events To post an event, we need to pass an event object to the EventBus.post method. EventBus will call the registered subscriber handler methods, taking arguments those are assignable to the event object type. This is a very powerful concept because interfaces, superclasses, and interfaces implemented by superclasses are included, meaning we can easily make our event handlers as course- or fine-grained as we want, simply by changing the type accepted by the event-handling method. Defining handler methods Methods used as event handlers must accept only one argument, the event object. As mentioned before, EventBus will call event-handling methods serially, so it's important that those methods complete quickly. If any extended processing needs to be done as a result of receiving an event, it's best to run that code in a separate thread. Concurrency EventBus will not call the handler methods from multiple threads, unless the handler method is marked with the @AllowConcurrentEvent annotation. By marking a handler method with the @AllowConcurrentEvent annotation, we are asserting that our handler method is thread-safe. Annotating a handler method with the @AllowConcurrentEvent annotation by itself will not register a method with EventBus. Now that we have defined how we can use EventBus, let's look at some examples. Subscribe – An example Let's assume we have defined the following TradeAccountEvent class as follows: public class TradeAccountEvent { private double amount; private Date tradeExecutionTime; private TradeType tradeType; private TradeAccount tradeAccount; public TradeAccountEvent(TradeAccount account, double amount, Date tradeExecutionTime, TradeType tradeType) { checkArgument(amount > 0.0, "Trade can't be less than zero"); this.amount = amount; this.tradeExecutionTime = checkNotNull(tradeExecutionTime,"ExecutionTime can't be null"); this.tradeAccount = checkNotNull(account,"Account can't be null"); this.tradeType = checkNotNull(tradeType,"TradeType can't be null"); } //Details left out for clarity So whenever a buy or sell transaction is executed, we will create an instance of the TradeAccountEvent class. Now let's assume we have a need to audit the trades as they are being executed, so we have the SimpleTradeAuditor class as follows: public class SimpleTradeAuditor { private List<TradeAccountEvent> tradeEvents = Lists.newArrayList(); public SimpleTradeAuditor(EventBus eventBus){ eventBus.register(this); } @Subscribe public void auditTrade(TradeAccountEvent tradeAccountEvent){ tradeEvents.add(tradeAccountEvent); System.out.println("Received trade "+tradeAccountEvent); } } Let's quickly walk through what is happening here. In the constructor, we are receiving an instance of an EventBus class and immediately register the SimpleTradeAuditor class with the EventBus instance to receive notifications on TradeAccountEvents. We have designated auditTrade as the event-handling method by placing the @Subscribe annotation on the method. In this case, we are simply adding the TradeAccountEvent object to a list and printing out to the console acknowledgement that we received the trade. Event Publishing – An example Now let's take a look at a simple event publishing example. For executing our trades, we have the following class: public class SimpleTradeExecutor { private EventBus eventBus; public SimpleTradeExecutor(EventBus eventBus) { this.eventBus = eventBus; } public void executeTrade(TradeAccount tradeAccount, double amount, TradeType tradeType){ TradeAccountEvent tradeAccountEvent = processTrade(tradeAccount, amount, tradeType); eventBus.post(tradeAccountEvent); } private TradeAccountEvent processTrade(TradeAccount tradeAccount, double amount, TradeType tradeType){ Date executionTime = new Date(); String message = String.format("Processed trade for %s of amount %n type %s @ %s",tradeAccount,amount,tradeType,executionTime); TradeAccountEvent tradeAccountEvent = new TradeAccountEvent(tradeAccount,amount,executionTime,tradeType); System.out.println(message); return tradeAccountEvent; } } Like the SimpleTradeAuditor class, we are taking an instance of the EventBus class in the SimpleTradeExecutor constructor. But unlike the SimpleTradeAuditor class, we are storing a reference to the EventBus for later use. While this may seem obvious to most, it is critical for the same instance to be passed to both classes. We will see in future examples how to use multiple EventBus instances, but in this case, we are using a single instance. Our SimpleTradeExecutor class has one public method, executeTrade, which accepts all of the required information to process a trade in our simple example. In this case, we call the processTrade method, passing along the required information and printing to the console that our trade was executed, then returning a TradeAccountEvent instance. Once the processTrade method completes, we make a call to EventBus.post with the returned TradeAccountEvent instance, which will notify any subscribers of the TradeAccountEvent object. If we take a quick view of both our publishing and subscribing examples, we see that although both classes participate in the sharing of required information, neither has any knowledge of the other. Finer-grained subscribing We have just seen examples on publishing and subscribing using the EventBus class. If we recall, EventBus publishes events based on the type accepted by the subscribed method. This gives us some flexibility to send events to different subscribers by type. For example, let's say we want to audit the buy and sell trades separately. First, let's create two separate types of events: public class SellEvent extends TradeAccountEvent { public SellEvent(TradeAccount tradeAccount, double amount, Date tradExecutionTime) { super(tradeAccount, amount, tradExecutionTime, TradeType.SELL); } } public class BuyEvent extends TradeAccountEvent { public BuyEvent(TradeAccount tradeAccount, double amount, Date tradExecutionTime) { super(tradeAccount, amount, tradExecutionTime, TradeType.BUY); } } Now we have created two discrete event classes, SellEvent and BuyEvent, both of which extend the TradeAccountEvent class. To enable separate auditing, we will first create a class for auditing SellEvent instances: public class TradeSellAuditor { private List<SellEvent> sellEvents = Lists.newArrayList(); public TradeSellAuditor(EventBus eventBus) { eventBus.register(this); } @Subscribe public void auditSell(SellEvent sellEvent){ sellEvents.add(sellEvent); System.out.println("Received SellEvent "+sellEvent); } public List<SellEvent> getSellEvents() { return sellEvents; } } Here we see functionality that is very similar to the SimpleTradeAuditor class with the exception that this class will only receive the SellEvent instances. Then we will create a class for auditing only the BuyEvent instances: public class TradeBuyAuditor { private List<BuyEvent> buyEvents = Lists.newArrayList(); public TradeBuyAuditor(EventBus eventBus) { eventBus.register(this); } @Subscribe public void auditBuy(BuyEvent buyEvent){ buyEvents.add(buyEvent); System.out.println("Received TradeBuyEvent "+buyEvent); } public List<BuyEvent> getBuyEvents() { return buyEvents; } } Now we just need to refactor our SimpleTradeExecutor class to create the correct TradeAccountEvent instance class based on whether it's a buy or sell transaction: public class BuySellTradeExecutor { … deatails left out for clarity same as SimpleTradeExecutor //The executeTrade() method is unchanged from SimpleTradeExecutor private TradeAccountEvent processTrade(TradeAccount tradeAccount, double amount, TradeType tradeType) { Date executionTime = new Date(); String message = String.format("Processed trade for %s of amount %n type %s @ %s", tradeAccount, amount, tradeType, executionTime); TradeAccountEvent tradeAccountEvent; if (tradeType.equals(TradeType.BUY)) { tradeAccountEvent = new BuyEvent(tradeAccount, amount, executionTime); } else { tradeAccountEvent = new SellEvent(tradeAccount, amount, executionTime); } System.out.println(message); return tradeAccountEvent; } } Here we've created a new BuySellTradeExecutor class that behaves in the exact same manner as our SimpleTradeExecutor class, with the exception that depending on the type of transaction, we create either a BuyEvent or SellEvent instance. However, the EventBus class is completely unaware of any of these changes. We have registered different subscribers and we are posting different events, but these changes are transparent to the EventBus instance. Also, take note that we did not have to create separate classes for the notification of events. Our SimpleTradeAuditor class would have continued to receive the events as they occurred. If we wanted to do separate processing depending on the type of event, we could simply add a check for the type of event. Finally, if needed, we could also have a class that has multiple subscribe methods defined: public class AllTradesAuditor { private List<BuyEvent> buyEvents = Lists.newArrayList(); private List<SellEvent> sellEvents = Lists.newArrayList(); public AllTradesAuditor(EventBus eventBus) { eventBus.register(this); } @Subscribe public void auditSell(SellEvent sellEvent){ sellEvents.add(sellEvent); System.out.println("Received TradeSellEvent "+sellEvent); } @Subscribe public void auditBuy(BuyEvent buyEvent){ buyEvents.add(buyEvent); System.out.println("Received TradeBuyEvent "+buyEvent); } } Here we've created a class with two event-handling methods. The AllTradesAuditor method will receive notifications about all trade events; it's just a matter of which method gets called by EventBus depending on the type of event. Taken to an extreme, we could create an event handling method that accepts a type of Object, as Object is an actual class (the base class for all other objects in Java), and we could receive notifications on any and all events processed by EventBus. Finally, there is nothing preventing us from having more than one EventBus instance. If we were to refactor the BuySellTradeExecutor class into two separate classes, we could inject a separate EventBus instance into each class. Then it would be a matter of injecting the correct EventBus instance into the auditing classes, and we could have complete event publishing-subscribing independence. Unsubscribing to events Just as we want to subscribe to events, it may be desirable at some point to turn off the receiving of events. This is accomplished by passing the subscribed object to the eventBus.unregister method. For example, if we know at some point that we would want to stop processing events, we could add the following method to our subscribing class: public void unregister(){ this.eventBus.unregister(this); } Once this method is called, that particular instance will stop receiving events for whatever it had previously registered for. Other instances that are registered for the same event will continue to receive notifications. AsyncEventBus We stated earlier the importance of ensuring that our event-handling methods keep the processing light due to the fact that the EventBus processes all events in a serial fashion. However, we have another option with the AsyncEventBus class. The AsyncEventBus class offers the exact same functionality as the EventBus, but uses a provided java.util.concurrent.Executor instance to execute handler methods asynchronously. Creating an AsyncEventBus instance We create an AsyncEventBus instance in a manner similar to the EventBus instance: AsyncEventBus asyncEventBus = new AsyncEventBus(executorService); Here we are creating an AsyncEventBus instance by providing a previously created ExecutorService instance. We also have the option of providing a String identifier in addition to the ExecutorService instance. AsyncEventBus is very helpful to use in situations where we suspect the subscribers are performing heavy processing when events are received. DeadEvents When EventBus receives a notification of an event through the post method, and there are no registered subscribers, the event is wrapped in an instance of a DeadEvent class. Having a class that subscribes for DeadEvent instances can be very helpful when trying to ensure that all events have registered subscribers. The DeadEvent class exposes a getEvent method that can be used to inspect the original event that was undelivered. For example, we could provide a very simple class, which is shown as follows: public class DeadEventSubscriber { private static final Logger logger = Logger.getLogger(DeadEventSubscriber.class); public DeadEventSubscriber(EventBus eventBus) { eventBus.register(this); } @Subscribe public void handleUnsubscribedEvent(DeadEvent deadEvent){ logger.warn("No subscribers for "+deadEvent.getEvent()); } } Here we are simply registering for any DeadEvent instances and logging a warning for the original unclaimed event. Dependency injection To ensure we have registered our subscribers and publishers with the same instance of an EventBus class, using a dependency injection framework (Spring or Guice) makes a lot of sense. In the following example, we will show how to use the Spring Framework Java configuration with the SimpleTradeAuditor and SimpleTradeExecutor classes. First, we need to make the following changes to the SimpleTradeAuditor and SimpleTradeExecutor classes: @Component public class SimpleTradeExecutor { private EventBus eventBus; @Autowired public SimpleTradeExecutor(EventBus eventBus) { this.eventBus = checkNotNull(eventBus, "EventBus can't be null"); } @Component public class SimpleTradeAuditor { private List<TradeAccountEvent> tradeEvents = Lists.newArrayList(); @Autowired public SimpleTradeAuditor(EventBus eventBus){ checkNotNull(eventBus,"EventBus can't be null"); eventBus.register(this); } Here we've simply added an @Component annotation at the class level for both the classes. This is done to enable Spring to pick these classes as beans, which we want to inject. In this case, we want to use constructor injection, so we added an @Autowired annotation to the constructor for each class. Having the @Autowired annotation tells Spring to inject an instance of an EventBus class into the constructor for both objects. Finally, we have our configuration class that instructs the Spring Framework where to look for components to wire up with the beans defined in the configuration class. @Configuration @ComponentScan(basePackages = {"bbejeck.guava.article7.publisher", "bbejeck.guava.article7.subscriber"}) public class EventBusConfig { @Bean public EventBus eventBus() { return new EventBus(); } } Here we have the @Configuration annotation, which identifies this class to Spring as a Context that contains the beans to be created and injected if need be. We defined the eventBus method that constructs and returns an instance of an EventBus class, which is injected into other objects. In this case, since we placed the @Autowired annotation on the constructors of the SimpleTradeAuditor and SimpleTradeExecutor classes, Spring will inject the same EventBus instance into both classes, which is exactly what we want to do. While a full discussion of how the Spring Framework functions is beyond the scope of this book, it is worth noting that Spring creates singletons by default, which is exactly what we want here. As we can see, using a dependency injection framework can go a long way in ensuring that our event-based system is configured properly. Summary In this article, we have covered how to use event-based programing to reduce coupling in our code by using the Guava EventBus class. We covered how to create an EventBus instance and register subscribers and publishers. We also explored the powerful concept of using types to register what events we are interested in receiving. We learned about the AsyncEventBus class, which allows us to dispatch events asynchronously. We saw how we can use the DeadEvent class to ensure we have subscribers for all of our events. Finally, we saw how we can use dependency injection to ease the setup of our event-based system. In the next article, we will take a look at working with files in Guava. Resources for Article: Further resources on this subject: WordPress: Avoiding the Black Hat Techniques [Article] So, what is Google Drive? [Article] Showing your Google calendar on your Joomla! site using GCalendar [Article]
Read more
  • 0
  • 0
  • 3664

article-image-working-java-se-projects-should-know
Packt
25 Nov 2013
5 min read
Save for later

Working with Java SE projects (Should know)

Packt
25 Nov 2013
5 min read
(For more resources related to this topic, see here.) How to do it... The following steps will show you how to experiment with JRebel on a Java SE application: Create a simple Swing application and test it. Enable JRebel on your project. Try live code injection with JRebel. How it works... We will create a simple Swing application, a frame that contains a label and a button. The action associated with the button will update the label. We will use JRebel to change the button's action without recompiling or restarting the application. Start NetBeans and create a new Java application project. Create a package, delete the default main class, and use the NetBeans assistant to create a new JFrame object by navigating to File | New File | Swing GUI Forms | JFrame Form, and then choose a name and validate. The Projects view Use the Palette tab on your right to drag-and-drop a JLabel and a JButton to your JForm (these two components are located in the Swing Controls section, under the Label and Button names). The Palette tab Now, double-click on the button you have generated. You will be redirected to the jButton1ActionPerformed method of your JFrame object. private void jButton1ActionPerformed (java.awt.event.ActionEvent evt) { // TODO add your handling code here: } Insert a code to update JLabel of your form, as shown in the following code: private void jButton1ActionPerformed (java.awt.event.ActionEvent evt) { // TODO add your handling code here: jLabel1.setText("Hello World"); } The application is now ready for testing. You can test it by pressing F6 key. NetBeans will ask you for the name of the main class. Select the JFrame form and validate. Use the jButton1 button to update the label. The first Hello World window Do not close the application immediately, and return to the code editor to update the jButton1 button's action in order to display a new message and save the new code. private void jButton1ActionPerformed (java.awt.event.ActionEvent evt) { // TODO add your handling code here: // jLabel1.setText("Hello World"); // previous message jLabel1.setText("Hello Planet"); // new message } Hit the jButton1 button in your application again; the change is not effective. Actually, your application hasn't been updated and it can't reflect code changes immediately. You will have to restart your application to see the new behavior, and this is normal. Now, let's see how JRebel will accelerate the development. You may have noticed the presence of a JRebel node in the Projects view. Right-click on it and choose Generate rebel.xml. The JRebel XML The rebel.xml file will contain the path of the compiled classes. JRebel will use these compiled classes to update your running application. Also, that means we have to ensure the Compile on Save feature is turned on for your project. Every time you apply changes to a Java class, NetBeans will recompile it and JRebel will update your running application with it. To proceed, go to the Projects Properties panel and enable the Compile on Save feature. Enabling the Compile on Save feature To finish, you have to activate JRebel (locate the JRebel button on the NetBeans toolbar). Enabling the JRebel button Now, restart your application and hit the jButton1 button a first time. Return to the code editor, modify the button's action to display a new message, save, and carefully observe the NetBeans console; you will see two interesting messages: Firstly, JRebel indicates if your license is active Secondly, you can see a message that indicates a class which has been reloaded, as follows: 2013-07-28 15:08:03 JRebel: Reloading class 'demo.ant.OurJFrame'. 2013-07-28 15:08:03 JRebel: Reloading class 'demo.ant. OurJFrame$2'. 2013-07-28 15:08:03 JRebel: Reloading class 'demo.ant. OurJFrame$1'. Hit the jButton1 button again; the message changes without restarting the application. It works! You can now continue to update and save code in order to see the changes. Try to update the displayed message again, it works again; you don't need to restart your application again (except for some changes that are not supported by JRebel). There's more... Ant is not the only build system, so you may want to use JRebel with Maven-based projects. Maven- and Ant-based projects are handled the same way: generate a rebel.xml file, activate the Compile on Save feature, enable JRebel, and simply update your code without restarting your application. You don't have to deal with the Maven pom.xml file. Also, you will still see the two same JRebel messages in the NetBeans console. They are useful to check the JRebel license and class reloading. Last but not least, to activate the Compile On Save feature, the Compile On Save menu should be set to For application execution only (or better). Maven's Compile On Save feature Summary In this article, we learnt how to work with JRebel on the Ant Java SE projects. We also learnt the about Maven Java SE projects support. Resources for Article: Further resources on this subject: The Business Layer (Java EE 7 First Look) [Article] Developing Secure Java EE Applications in GlassFish [Article] Service Oriented Java Business Integration - What's & Why's [Article]
Read more
  • 0
  • 0
  • 3662
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-microsoft-sharepoint-creating-various-content-types
Packt
02 Dec 2011
7 min read
Save for later

Microsoft SharePoint : Creating Various Content Types

Packt
02 Dec 2011
7 min read
(For more resources on Microsoft SharePoint, see here.) SharePoint content types are used to make it simpler for site managers to standardize what content and associated metadata gets uploaded to lists and libraries on the site. In this article, we'll take a look at how you can create various content types and assign them to be used in site containers. As a subset of more complex content types, a document set will allow your users to store related items in libraries as a set of documents sharing common metadata. This approach will allow your users to run business processes on a batch of items in the document set as well as the whole set. In this article, we'll take a look at how you can define a document set to be used on your site. Since users mostly interact with your SharePoint site through pages and views, the ability to modify SharePoint pages to accommodate business user requirements becomes an important part of site management. In this article, we'll take a look at how you can create and modify pages and content related to them. We will also take a look at how you can provision simple out-of-the-box web parts to your SharePoint publishing pages and configure their properties. Creating basic and complex content types SharePoint lists and libraries can store a variety of content on the site. SharePoint also has a user interface to customize what information you can collect from users to be attached as an item metadata. In the scenario where the entire intranet or the department site within your organization requires a standard set of metadata to be collected with list and library items, content types are the easiest approach to implement the requirement. With content types, you can define the type of business content your users will be interacting with. Once defined, you can also add a metadata field and any applicable validation to them. Once defined, you can attach the newly created content type to the library or list of your choice so that newly uploaded or modified content can conform to the rules you defined on the site. Getting ready Considering you have already set up your virtual development environment, we'll get right into authoring our script. It's assumed you are familiar with how to interact with SharePoint lists and libraries using PowerShell. In this recipe, we'll be using PowerGUI to author the script, which means you will be required to be logged in with an administrator's role on the target Virtual Machine. How to do it... Let's take a look at how we can provision site content types using PowerShell as follows: Click Start | All Programs | PowerGUI | PowerGUI Script Editor. In the main script editing window of PowerGUI, add the following script: # Defining script variables$SiteUrl = "http://intranet.contoso.com"$ListName = "Shared Documents"# Loading Microsoft.SharePoint.PowerShell $snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}if ($snapin -eq $null) {Write-Host "Loading SharePoint Powershell Snapin"Add-PSSnapin "Microsoft.SharePoint.Powershell"}$SPSite = Get-SPSite | Where-Object {$_.Url -eq $SiteUrl} if($SPSite -ne $null) { Write-Host "Connecting to the site" $SiteUrl ",list " $ListName $RootWeb = $SPSite.RootWeb $SPList = $RootWeb.Lists[$ListName] Write-Host "Creating new content type from base type" $DocumentContentType = $RootWeb.AvailableContentTypes["Document"] $ContentType = New-Object Microsoft.SharePoint.SPContentType -ArgumentList @($DocumentContentType, $RootWeb.ContentTypes, "Org Document") Write-Host "Adding content type to site" $ct = $RootWeb.ContentTypes.Add($ContentType) Write-Host "Creating new fields" $OrgDocumentContentType = $RootWeb.ContentTypes[$ContentType.Id] $OrgFields = $RootWeb.Fields $choices = New-Object System.Collections.Specialized.StringCollection $choices.Add("East") $choices.Add("West") $OrgDivision = $OrgFields.Add("Division", [Microsoft.SharePoint.SPFieldType]::Choice, $false, $false, $choices) $OrgBranch = $OrgFields.Add("Branch", [Microsoft.SharePoint.SPFieldType]::Text, $false) Write-Host "Adding fields to content type" $OrgDivisionObject = $OrgFields.GetField($OrgDivision) $OrgBranchObject = $OrgFields.GetField($OrgBranch) $OrgDocumentContentType.FieldLinks.Add($OrgDivisionObject) $OrgDocumentContentType.FieldLinks.Add($OrgBranchObject) $OrgDocumentContentType.Update() Write-Host "Associating content type to list" $ListName $association = $SPList.ContentTypes.Add($OrgDocumentContentType) $SPList.ContentTypesEnabled = $true $SPList.Update() Write-Host "Content type provisioning complete" } $SPSite.Dispose() Click File | Save to save the script to your development machine's desktop. Set the filename of the script to CreateAssociateContentType.ps1. Open the PowerShell console window and call CreateAssociateContentType. ps1 using the following command: PS C:UsersAdministratorDesktop> . CreateAssociateContentType.ps1 As a result, your PowerShell script will create a site structure as shown in the following screenshot: Now, from your browser, let's switch to our SharePoint Intranet: http://intranet.contoso.com. From the home page's Quick launch, click the Shared Documents link. On the ribbon, click the Library tab and select Settings | Library Settings. Take note of the newly associated content type added to the Content Types area of the library settings, as shown in the following screenshot: Navigate back to the Shared Documents library from the Quick launch menu on your site and select any of the existing documents in the library. From the ribbons Documents tab, click Manage | Edit Properties. Take note of how the item now has the Content Type option available, where you can pick newly provisioned Org Document content type. Pick the Org Document content type and take note of the associated metadata showing up for the new content type, as shown in the following screenshot: How it works... First, we defined the script variables. In this recipe, the variables include a URL of the site where the content types are provisioned, http://intranet.contoso.com, and a document library to which the content type is associated: $ListName = "Shared Documents" Once a PowerShell snap-in has been loaded, we get a hold of the instance of the current site and its root web. Since we want our content type to inherit from the parent rather than just being defined from the scratch, we get a hold of the existing parent content type first, using the following command: $DocumentContentType = $RootWeb.AvailableContentTypes["Document"] Next, we created an instance of a new content type inheriting from our parent content type and provisioned it to the root site using the following command: $ContentType = New-Object Microsoft.SharePoint.SPContentType -ArgumentList @($DocumentContentType, $RootWeb.ContentTypes, "Org Document") Here, the new object takes the following parameters: the content type representing a parent, a web to which the new content type will be provisioned to, and the display name for the content type. Once our content type object has been created, we add it to the list of existing content types on the site: $ct = $RootWeb.ContentTypes.Add($ContentType) Since most content types are unique by the fields they are using, we will add some business- specific fields to our content type. First, we get a hold of the collection of all of the available fields on the site: $OrgFields = $RootWeb.Fields Next, we create a string collection to hold the values for the choice field we are going to add to our content type: $choices = New-Object System.Collections.Specialized.StringCollection The field with list of choices was called Division, representing a company division. We provision the field to the site using the following command: $OrgDivision = $OrgFields.Add("Division", [Microsoft.SharePoint.SPFieldType]::Choice, $false, $false, $choices) In the preceding command, the first parameter is the name of the field, followed by the type of the field, which in our case is choice field. We then specify whether the field will be a required field, followed by a parameter indicating whether the field name will be truncated to eight characters. The last parameter specifies the list of choices for the choice field. Another field we add, representing a company branch, is simpler since it's a text field. We define the text field using the following command: $OrgBranch = $OrgFields.Add("Branch", [Microsoft.SharePoint.SPFieldType]::Text, $false) We add both fields to the content type using the following commands: $OrgDocumentContentType.FieldLinks.Add($OrgDivisionObject)$OrgDocumentContentType.FieldLinks.Add($OrgBranchObject) The last part is to associate the newly created content type to a library, in our case Shared Documents. We use the following command to associate the content type to the library: $association = $SPList.ContentTypes.Add($OrgDocumentContentType) To ensure the content types on the list are enabled, we set the ContentTypesEnabled property of the list to $true.  
Read more
  • 0
  • 0
  • 3661

article-image-troubleshooting-your-bam-applications
Packt
21 Nov 2012
9 min read
Save for later

Troubleshooting your BAM Applications

Packt
21 Nov 2012
9 min read
(For more resources related to this topic, see here.) Understanding BAM logging and troubleshooting methodologies In many cases, enabling BAM logging is the prerequisite for troubleshooting BAM issues. It is critical to set up the correct loggers to appropriate levels (for example, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, and FINEST), so that you can collect the information to identify the actual problem, and determine the root cause. Apart from logging, it is also important to have the proven methodologies in place, so that you can follow these methods/procedures to conduct your troubleshooting practice. Understanding BAM logging concepts BAM provides a set of loggers, which are associated with BAM Java packages/ classes. Like Java, these loggers are named by following the dot convention, and are organized hierarchically. Let's take a look at an example. oracle.bam.adc is the root logger for the Active Data Cache. All the loggers for the sub-modules within the Active Data Cache should be named after oracle.bam.adc, and therefore become descendants of the root logger. For instance, oracle.bam.adc.security, which is the logger that tracks Active Data Cache security logs, is the child logger of oracle.bam.adc. The logging level for the descendant/child (for example, oracle.bam.adc.security)inherits from the ancestor/parent (for example, oracle.bam.adc adc) by default, unless its logging level is explicitly specified. Thus, you should be careful when setting a root or parent logger to a low level (for example, TRACE:32 ), which may produce a large amount of log entries in the log file The following table lists the major root-level loggers for troubleshooting key BAM components: Logger name Description oracle.bam.adapter This is the logger for troubleshooting the BAM Adapter issues oracle.bam.adc This is the logger for troubleshooting the BAM Active Data Cache operations, such as data persistence, ADC APIs, Active Data processing with ADC, and so on orable.bam.common This is the logger for debugging BAM common components, for example, BAM Security or BAM Messaging Framework oracle.bam.ems This is the logger for debugging BAM Enterprise Message Sources (EMS) oracle.bam.eventengine This is the logger for debugging the Event Engine oracle.bam.reportcache This is the logger for debugging the Report Cache oracle.bam.web This is the logger for debugging the BAM web applications, which include the Report Server oracle.bam.webservices This is the logger for debugging the BAM web services interface Enabling logging for BAM To set up loggers for BAM, perform the following steps: Log in to Enterprise Manager 11g Fusion Middleware Control. Click on OracleBamServer(bam_server1) from the left pane, and select BAM Server | Logs | Log Configuration. Expand oracle.bam to set the BAM loggers. To ensure that the log-level changes are persistent, check the checkbox for Persist log level state across component restarts. Click on Apply. The logs are written to the <server_name>-diagnostic.log file in the <mserver_domain_dir>/servers/<server_name>/logs directory. By default, the log file follows the size-based rotation policy, and the rotational size is 10M. You can change the default behavior by editing the log file configuration as follows: Log in to Enterprise Manager 11g Fusion Middleware Control. Click on OracleBamServer(bam_server1) from the left pane, and select BAM Server | Logs | Log Configuration. In the Log Configurations screen, click on the Log Files tab. Select odl-handler, and then click on Edit Configuration Edit the log file configuration, and click on OK. Setting BAM loggers to appropriate values Similar to what most Fusion Middleware components do, Oracle BAM uses the lo g levels specified in the Oracle Diagnostic Logging (ODL) standard to control the log details in the diagnostic log file. Similar to the log levels in Java, ODL log levels and their descriptions are listed in the following table: Log level (Java) Log level (ODL) Description SEVERE+100 INCIDENT_ ERROR:1 This log level enables the BAM Server that reports critical issues or fatal errors. SEVERE ERROR:1 This log level enables the BAM Server components to report issues (system errors, exceptions, or malfunctions) that may prevent the system from working properly. WARNING WARNING:1 This log level enables the BAM Server components to report events or conditions that should be reviewed and may require actions. INFO NOTIFICATION:1 This is the default setting for all the BAM loggers. This log level is used to capture the lifecycle events of BAM Server components and the key messages for notification purposes. For example, if you need to verify the cache location or its running status for the BAM Report Cache, you can set the report cache logger to this log level. CONFIG NOTIFICATION:16 This log level enables the BAM Server components to write more detailed configuration information. FINE TRACE:1 This log level enables the BAM Server components to write the debug information to the log file. To  troubleshoot the BAM server components, you may start with this log level, and increase to FINER or FINEST, if needed. FINER TRACE:16 This log level enables the BAM Server components to write a fairly detailed debug information to the log file. FINEST TRACE:32 This log level enables the BAM Server components to write a highly detailed debug information. Inherited from parent   Specify this value if you want a specific logger to inherit the log level from its parent logger. The default setting for all BAM loggers is NOTIFICATION:1. For troubleshooting purposes, it is recommended to set the appropriate loggers to TRACE:1, TRACE:16, or TRACE:32. The logging configuration is persisted in the following location on your BAM host: <domain_dir>/config/fmwconfig/ servers/<server_name>/logging.xml. Theoretically, you can edit this file to modify BAM loggers. However, it is not recommended to do so unless you have a good understanding of the configuration file. If you have multiple BAM instances in your environment, you can easily duplicate the logging configuration by copying the logging.xml file to all BAM instances, rather than making changes through EM. Introducing the methodologies for troubleshooting BAM Oracle BAM utilizes different technologies such as EMS, BAM Adapter, Web services, and ODI to integrate different enterprise information systems. Business data received from various data sources are then pushed all the way from the Active Data Cache, through the Report Cache and the Report Server, to Web browsers for rendering reports in real-time. Due to the complexity of the system and various technologies involved, it is critical to use the right troubleshooting methodologies to analyze and resolve issues. The following are the basic rules of thumb for troubleshooting your BAM applications: Understand the BAM key terminologies and architecture Identify the problem Set up BAM loggers Collect the information and debugging Understanding the key terminologies and the BAM architecture Understanding the key terminologies and the BAM architecture is a prerequisite for troubleshooting the BAM applications. The key terminologies for BAM include Active Data, Active Data Cache, Report Cache, Report Server, ChangeList, Data Objects, Report, and so on. Identifying the problem Different issues may require different techniques to troubleshoot. For example, for a report design issue (for example, calculated fields do not show correct values), you should focus on the building blocks for the report design, instead of enabling loggings for the BAM server, which does not provide any help at all. A BAM issue typically falls into the following categories: Report design and report loading (static rendering) Report rendering with Active Data (Active Data processing) Issues with the key BAM Server components (Active Data Cache, securities, Report Cache, and Event Engine) BAM Web applications (Active Viewer, Active Studio, Architect, Administrator, and Report Server) Issues with BAM Integration Framework (EMS, Web services APIs, SOA Suite integration, and ODI integration) To fully identify a problem, you need to first understand the problem description and the category to which the issue belongs. Then, you can gather relevant information, such as the time frame of when the issue happened, the BAM Server release information and patch level, BAM deployment topologies (single node or HA), and so on. Setting up BAM loggers Setting up BAM loggers with appropriate logging levels is the key for troubleshooting BAM issues. BAM loggers can be set up to the following levels (Java logging): SEVERE, WARNING, INFO, CONFIG, FINE, FINER, and FINEST. In a normal situation, all the BAM loggers are set to INFO, by default. In the case of debugging, it is recommended to increase the level to FINER or FINEST. Loggers contain hierarchies. You need to be careful when setting up root level loggers to FINE, FINER, or FINEST. Suppose that you want to troubleshoot a login issue with the BAM start page using the root logger oracle.bam.adc, which is set to FINEST. In this case, all the descendants that inherit from it have the same logging level. As a result, a large amount of unused log entries are produced, which is not helpful for troubleshooting, and can also impact the overall performance. Therefore, you should set up the corresponding child logger (oracle.bam.adc.security) without enabling the root logger.Collecting information and debugging. Once the problem is identified and BAM loggers are set up appropriately, it is time to collect the logs to analyze the problem. The following table lists the files that can be used to troubleshoot BAM issues: Name Description <server_name>.out This is the standard output file redirected by the Node Manager. If the server is started using the  tartManagedWebLogic.sh script directly, you need to refer to the standard output (either the command prompt output or another redirected file specified). This file is located in the following directory: <mserver_domain_dir>/servers/<server_name>/logs. <mserver_domain_dir> refers to the domain home directory for the Managed Server for BAM; <server_name> refers to the name of the Managed Server for BAM, for example, WLS_BAM1. Use this file to collect the server starting information and standard output. <server_name>.log This log provides information for the WebLogic Server that hosts BAM. This file is located in the following directory: <mserver_domain_dir>/servers/<server_name>/logs. <server_name>-diagnostic.log Unlike the <server_name>.log file, this log file keeps a track of BAM-specific logs produced by BAM loggers. The location of this file is as follows: <mserver_domain_dir>/servers/<server_name>/logs. Debugging actually becomes easier once you have all this relevant information in place.
Read more
  • 0
  • 0
  • 3646

article-image-combining-vector-and-raster-datasets
Packt
22 Dec 2014
12 min read
Save for later

Combining Vector and Raster Datasets

Packt
22 Dec 2014
12 min read
This article by Michael Dorman, the author of Learning R for Geospatial Analysis, explores the interplay between vector and raster layers, and the way it is implemented in the raster package. The way rasters and vector layers can be interchanged and queried one according to the other will be demonstrated through examples. (For more resources related to this topic, see here.) Creating vector layers from a raster The opposite operation to rasterization, which has been presented in the previous section, is the creation of vector layers from raster data. The procedure of extracting features of interest out of rasters, in the form of vector layers, is often necessary for analogous reasons underlying rasterization—when the data held in a raster is better represented using a vector layer, within the context of specific subsequent analysis or visualization tasks. Scenarios where we need to create points, lines, and polygons from a raster can all be encountered. In this section, we are going to see an example of each. Raster-to-points conversion In raster-to-points conversion, each raster cell center (excluding NA cells) is converted to a point. The resulting point layer has an attribute table with the values of the respective raster cells in it. Conversion to points can be done with the rasterToPoints function. This function has a parameter named spatial that determines whether the returned object is going to be SpatialPointsDataFrame or simply a matrix holding the coordinates, and the respective cell values (spatial=FALSE, the default value). For our purposes, it is thus important to remember to specify spatial=TRUE. As an example of a raster, let's create a subset of the raster r, with only layers 1-2, rows 1-3, and columns 1-3: > u = r[[1:2]][1:3, 1:3, drop = FALSE] To make the example more instructive, we will place NA in some of the cells and see how this affects the raster-to-points conversion: > u[2, 3] = NA > u[[1]][3, 2] = NA Now, we will apply rasterToPoints to create a SpatialPointsDataFrame object named u_pnt out of u: > u_pnt = rasterToPoints(u, spatial = TRUE) Let's visually examine the result we got with the first layer of u serving as the background: > plot(u[[1]]) > plot(u_pnt, add = TRUE) The graphical output is shown in the following screenshot: We can see that a point has been produced at the center of each raster cell, except for the cell at position (2,3), where we assigned NA to both layers. However, at the (3,2) position, NA has been assigned to only one of the layers (the first one); therefore, a point feature has been generated there nevertheless. The attribute table of u_pnt has eight rows (since there are eight points) and two columns (corresponding to the raster layers). > u_pnt@data layer.1 layer.2 1 0.4242 0.4518 2 0.3995 0.3334 3 0.4190 0.3430 4 0.4495 0.4846 5 0.2925 0.3223 6 0.4998 0.5841 7     NA 0.5841 8 0.7126 0.5086 We can see that the seventh point feature, the one corresponding to the (3,2) raster position, indeed contains an NA value corresponding to layer 1. Raster-to-contours conversion Creating points (see the previous section) and polygons (see the next section) from a raster is relatively straightforward. In the former case, points are generated at cell centroids, while in the latter, rectangular polygons are drawn according to cell boundaries. On the other hand, lines can be created from a raster using various different algorithms designed for more specific purposes. Two common procedures where lines are generated based on a raster are constructing contours (lines connecting locations of equal value on the raster) and finding least-cost paths (lines going from one location to another along the easiest route when cost of passage is defined by raster values). In this section, we will see an example of how to create contours (readers interested in least-cost path calculation can refer to the gdistance package, which provides this capability in R). As an example, we will create contours from the DEM of Haifa (dem). Creating contours can be done using the rasterToContour function. This function accepts a RasterLayer object and returns a SpatialLinesDataFrame object with the contour lines. The rasterToContour function internally uses the base function contourLines, and arguments can be passed to the latter as part of the rasterToContour function call. For example, using the levels parameter, we can specify the breaks where contours will be generated (rather than letting them be determined automatically). The raster dem consists of elevation values ranging between -14 meters and 541 meters: > range(dem[], na.rm = TRUE) [1] -14 541 Therefore, we may choose to generate six contour lines, at 0, 100, 200, …, 500 meter levels: > dem_contour = rasterToContour(dem, levels = seq(0, 500, 100)) Now, we will plot the resulting SpatialLinesDataFrame object on top of the dem raster: > plot(dem) > plot(dem_contour, add = TRUE) The graphical output is shown in the following screenshot: Mount Carmel is densely covered with elevation contours compared to the plains surrounding it, which are mostly within the 0-100 meter elevation range and thus, have only few a contour lines. Let's take a look at the attribute table of dem_contour: > dem_contour@data    level C_1     0 C_2   100 C_3   200 C_4   300 C_5   400 C_6   500 Indeed, the layer consists of six line features—one for each break we specified with the levels argument. Raster-to-polygons conversion As mentioned previously, raster-to-polygons conversion involves the generation of rectangular polygons in the place of each raster cell (once again, excluding NA cells). Similar to the raster-to-points conversion, the resulting attribute table contains the respective raster values for each polygon created. The conversion to polygons is most useful with categorical rasters when we would like to generate polygons defining certain areas in order to exploit the analysis tools this type of data is associated with (such as extraction of values from other rasters, geometry editing, and overlay). Creation of polygons from a raster can be performed with a function whose name the reader may have already guessed, rasterToPolygons. A useful option in this function is to immediately dissolve the resulting polygons according to their attribute table values; that is, all polygons having the same value are dissolved into a single feature. This functionality internally utilizes the rgeos package and it can be triggered by specifying dissolve=TRUE. In our next example, we will visually compare the average NDVI time series of Lahav and Kramim forests (see earlier), based on all of our Landsat (three dates) and MODIS (280 dates) satellite images. In this article, we will only prepare the necessary data by going through the following intermediate steps: Creating the Lahav and Kramim forests polygonal layer. Extracting NDVI values from the satellite images. Creating a data.frame object that can be passed to graphical functions later. Commencing with the first step, using l_rec_focal_clump, we will first create a polygonal layer holding all NDVI>0.2 patches, then subset only those two polygons corresponding to Lahav and Kramim forests. The former is achieved using rasterToPolygons with dissolve=TRUE, converting the patches in l_rec_focal_clumpto 507 individual polygons in a new SpatialPolygonsDataFrame that we hereby name pol: > pol = rasterToPolygons(l_rec_focal_clump, dissolve = TRUE) Plotting pol will show that we have quite a few large patches and many small ones. Since the Lahav and Kramim forests are relatively large, to make things easier, we can omit all polygons with area less than or equal to 1 km2: > pol$area = gArea(pol, byid = TRUE) / 1000^2 > pol = pol[pol$area > 1, ] The attribute table shows that we are left with eight polygons, with area sizes of 1-10 km2. The clumps column, by the way, is where the original l_rec_focal_clump raster value (the clump ID) has been kept ("clumps" is the name of the l_rec_focal_clump raster layer from which the values came). > pol@data    clumps   area 112     2 1.2231 114   200 1.3284 137   221 1.9314 203   281 9.5274 240   314 6.7842 371   432 2.0007 445     5 10.2159 460     56 1.0998 Let's make a map of pol: > plotRGB(l_00, r = 3, g = 2, b = 1, stretch = "lin") > plot(pol, border = "yellow", lty = "dotted", add = TRUE) The graphical output is shown in the following screenshot: The preceding screenshot shows the continuous NDVI>0.2 patches, which are 1 km2 or larger, within the studied area. Two of these, as expected, are the forests we would like to examine. How can we select them? Obviously, we could export pol to a Shapefile and select the features of interest interactively in a GIS software (such as QGIS), then import the result back into R to continue our analysis. The raster package also offers some capabilities for interactive selection (that we do not cover here); for example, a function named click can be used to obtain the properties of the pol features we click in a graphical window such as the one shown in the preceding screenshot. However, given the purpose of this book, we will try to write a code to make the selection automatically without further user input. To write a code that makes the selection, we must choose a certain criterion (either spatial or nonspatial) that separates the features of interest. In this case, for example, we can see that the pol features we wish to select are those closest to Lahav Kibbutz. Therefore, we can utilize the towns point layer (see earlier) to find the distance of each polygon from Lahav Kibbutz, and select the two most proximate ones. Using the gDistance function, we will first find out the distances between each polygon in pol and each point in towns: > dist_towns = gDistance(towns, pol, byid = TRUE) > dist_towns              1         2 112 14524.94060 12697.151 114 5484.66695 7529.195 137 3863.12168 5308.062 203   29.48651 1119.090 240 1910.61525 6372.634 371 11687.63594 11276.683 445 12751.21123 14371.268 460 14860.25487 12300.319 The returned matrix, named dist_towns, contains the pairwise distances, with rows corresponding to the pol feature and columns corresponding to the towns feature. Since Lahav Kibbutz corresponds to the first towns feature (column "1"), we can already see that the fourth and fifth pol features (rows "203" and "240") are the most proximate ones, thus corresponding to the Lahav and Kramim forests. We could subset both forests by simply using their IDs—pol[c("203","240"),]. However, as always, we are looking for general code that will select, in this case, the two closest features irrespective of the specific IDs or row indices. For this purpose, we can use the order function, which we have not encountered so far. This function, given a numeric vector, returns the element indices in an increasing order according to element values. For example, applying order to the first column of dist_towns, we can see that the smallest element in this column is in the fourth row, the second smallest is in the fifth row, the third smallest is in the third row, and so on: > dist_order = order(dist_towns[, 1]) > dist_order [1] 4 5 3 2 6 7 1 8 We can use this result to select the relevant features of pol as follows: > forests = pol[dist_order[1:2], ] The subset SpatialPolygonsDataFrame, named forests, now contains only the two features from pol corresponding to the Lahav and Kramim forests. > forests@data    clumps   area 203   281 9.5274 240   314 6.7842 Let's visualize forests within the context of the other data we have by now. We will plot, once again, l_00 as the RGB background and pol on top of it. In addition, we will plot forests (in red) and the location of Lahav Kibbutz (as a red point). We will also add labels for each feature in pol, corresponding to its distance (in meters) from Lahav Kibbutz: > plotRGB(l_00, r = 3, g = 2, b = 1, stretch = "lin") > plot(towns[1, ], col = "red", pch = 16, add = TRUE) > plot(pol, border = "yellow", lty = "dotted", add = TRUE) > plot(forests, border = "red", lty = "dotted", add = TRUE) > text(gCentroid(pol, byid = TRUE), + round(dist_towns[,1]), + col = "White") The graphical output is shown in the following screenshot: The preceding screenshot demonstrates that we did indeed correctly select the features of interest. We can also assign the forest names to the attribute table of forests, relying on our knowledge that the first feature of forests (ID "203") is larger and more proximate to Lahav Kibbutz and corresponds to the Lahav forest, while the second feature (ID "240") corresponds to Kramim. > forests$name = c("Lahav", "Kramim") > forests@data    clumps   area   name 203   281 9.5274 Lahav 240   314 6.7842 Kramim We now have a polygonal layer named forests, with two features delineating the Lahav and Kramim forests, named accordingly in the attribute table. In the next section, we will proceed with extracting the NDVI data for these forests. Summary In this article, we closed the gap between the two main spatial data types (rasters and vector layers). We now know how to make the conversion from a vector layer to raster and vice versa, and we can transfer the geometry and data components from one data model to another when the need arises. We also saw how raster values can be extracted from a raster according to a vector layer, which is a fundamental step in many analysis tasks involving raster data. Resources for Article:  Further resources on this subject: Data visualization[article] Machine Learning in Bioinformatics[article] Specialized Machine Learning Topics[article]
Read more
  • 0
  • 0
  • 3646

article-image-nhibernate-30-using-linq-specifications-data-access-layer
Packt
21 Oct 2010
4 min read
Save for later

NHibernate 3.0: Using LINQ Specifications in the data access layer

Packt
21 Oct 2010
4 min read
  NHibernate 3.0 Cookbook Get solutions to common NHibernate problems to develop high-quality performance-critical data access applications Master the full range of NHibernate features Reduce hours of application development time and get better application architecture and performance Create, maintain, and update your database structure automatically with the help of NHibernate Written and tested for NHibernate 3.0 with input from the development team distilled in to easily accessible concepts and examples Part of Packt's Cookbook series: each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible         Read more about this book       (For more resources on NHibernate, see here.) Getting ready Download the LinqSpecs library from http://linqspecs.codeplex.com. Copy LinqSpecs.dll from the Downloads folder to your solution's libs folder. Complete the Setting up an NHibernate Repository recipe. How to do it... In Eg.Core.Data and Eg.Core.Data.Impl, add a reference to LinqSpecs.dll. Add these two methods to the IRepository interface. IEnumerable<T> FindAll(Specification<T> specification);T FindOne(Specification<T> specification); Add the following three methods to NHibernateRepository: public IEnumerable<T> FindAll(Specification<T> specification){ var query = GetQuery(specification); return Transact(() => query.ToList());}public T FindOne(Specification<T> specification){ var query = GetQuery(specification); return Transact(() => query.SingleOrDefault());}private IQueryable<T> GetQuery( Specification<T> specification){ return session.Query<T>() .Where(specification.IsSatisfiedBy());} Add the following specification to Eg.Core.Data.Queries: public class MoviesDirectedBy : Specification<Movie>{ private readonly string _director; public MoviesDirectedBy(string director) { _director = director; } public override Expression<Func<Movie, bool>> IsSatisfiedBy() { return m => m.Director == _director; }} Add another specification to Eg.Core.Data.Queries, using the following code: public class MoviesStarring : Specification<Movie>{ private readonly string _actor; public MoviesStarring(string actor) { _actor = actor; } public override Expression<Func<Movie, bool>> IsSatisfiedBy() { return m => m.Actors.Any(a => a.Actor == _actor); }} How it works... The specification pattern allows us to separate the process of selecting objects from the concern of which objects to select. The repository handles selecting objects, while the specification objects are concerned only with the objects that satisfy their requirements. In our specification objects, the IsSatisfiedBy method of the specification objects returns a LINQ expression to determine which objects to select. In the repository, we get an IQueryable from the session, pass this LINQ expression to the Where method, and execute the LINQ query. Only the objects that satisfy the specification will be returned. For a detailed explanation of the specification pattern, check out http://martinfowler.com/apsupp/spec.pdf. There's more... To use our new specifications with the repository, use the following code: var movies = repository.FindAll( new MoviesDirectedBy("Stephen Spielberg")); Specification composition We can also combine specifications to build more complex queries. For example, the following code will find all movies directed by Steven Speilberg starring Harrison Ford: var movies = repository.FindAll( new MoviesDirectedBy("Steven Spielberg") & new MoviesStarring("Harrison Ford")); This may result in expression trees that NHibernate is unable to parse. Be sure to test each combination. Summary In this article we covered: Using LINQ Specifications in the data access layer Further resources on this subject: NHibernate 3.0: Working with the Data Access Layer NHibernate 3.0: Using Named Queries in the Data Access Layer NHibernate 3.0: Using ICriteria and Paged Queries in the data access layer NHibernate 3.0: Testing Using NHibernate Profiler and SQLite Using the Fluent NHibernate Persistence Tester and the Ghostbusters Test
Read more
  • 0
  • 0
  • 3645
article-image-top-two-features-gson
Packt
03 Sep 2013
5 min read
Save for later

Top two features of GSON

Packt
03 Sep 2013
5 min read
(For more resources related to this topic, see here.) Java objects support Objects in GSON are referred as types of JsonElement: The GSON library can convert any user-defined class objects to and from the JSON representation. The Student class is a user-defined class, and GSON can serialize any Student object to JSON. The Student.java class is as follows: public class Student { private String name; private String subject; privateint mark; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public int getMark() { return mark; } public void setMark(int mark) { this.mark = mark; } } The code for JavaObjectFeaturesUse.java is as follows: import com.google.gson.Gson; import com.packt.chapter.vo.Student; public class JavaObjectFeaturesUse { public static void main(String[] args){ Gsongson = new Gson(); Student aStudent = new Student(); aStudent.setName("Sandeep"); aStudent.setMark(128); aStudent.setSubject("Computer Science"); String studentJson = gson.toJson(aStudent); System.out.println(studentJson); Student anotherStudent = gson.fromJson(studentJson, Student.class); System.out.println(anotherStudentinstanceof Student); } } The output of the preceding code is as follows: {"name":"Sandeep","subject":"Computer Science","mark":128} True The preceding code creates a Student object with name as Sandeep, subject as Computer Science, and marks as 128. A Gson object is then instantiated and the Student object is passed in as a parameter to the toJson() method. It returns a string that has the JSON representation of the Java object. This string is printed as the first line in the console. The output JSON representation of the Student object is a collection of key/value pairs. The Java property of the Student class becomes the key in the JSON string. In the last part of the code, the fromJson() method takes the JSON generated string as the first input parameter and Student.class as the second parameter, to convert the JSON string back to a Student Java object. The last line of the code uses an instance of Student as the second-line operator to verify whether the generated Java object by the fromJson() method is of type Student. In the console, it prints True as the output, and if we print the values, we will get the same values as in JSON. Serialization and deserialization GSON has implicit serializations for some classes, such as Java wrapper type (Integer, Long, Double, and so on), java.net.URL, java.net.URI, java.util.Date, and so on. Let's see an example: import java.util.Date; import com.google.gson.Gson; public class InbuiltSerializerFeature { public static void main(String[] args) { Date aDateJson = new Date(); Gsongson = new Gson(); String jsonDate = gson.toJson(aDateJson); System.out.println(jsonDate); } } The output of the preceding code is as follows: May 29, 2013 8:55:07 PM The preceding code is serializing the Java Date class object to its JSON representation. In the preceding section, you have learned how GSON is used to serialize and deserialize objects, and how it supports custom serializers and deserializers for user-defined Java class objects. Let's see how it works. Also, GSON provides the custom serialization feature to developers. The following code is an example of a custom serializer: classStudentTypeSerializer implements JsonSerializer<Student>{ @Override publicJsonElement serialize(Student student, Type type, JsonSerializationContextcontext) { JsonObjectobj = new JsonObject(); obj.addProperty("studentname", student.getName()); obj.addProperty("subjecttaken", student.getSubject()); obj.addProperty("marksecured", student.getMark()); returnobj; } } The following code is an example of a custom deserializer: classStudentTypeDeserializer implements JsonDeserializer<Student>{ @Override public Student deserialize(JsonElementjsonelment, Type type, JsonDeserializationContext context) throws JsonParseException { JsonObjectjsonObject = jsonelment.getAsJsonObject(); Student aStudent = new Student(); aStudent.setName(jsonObject.get("studentname").getAsString()); aStudent.setSubject(jsonObject.get("subjecttaken").getAsString()); aStudent.setMark(jsonObject.get("marksecured").getAsInt()); return aStudent; } } The following code tests the custom serializer and deserializer: import java.lang.reflect.Type; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; public class CustomSerializerFeature { public static void main(String[] args) { GsonBuildergsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Student.class, new StudentTypeSerializer()); Gsongson = gsonBuilder.create(); Student aStudent = new Student(); aStudent.setName("Sandeep"); aStudent.setMark(150); aStudent.setSubject("Arithmetic"); String studentJson = gson.toJson(aStudent); System.out.println("Custom Serializer : Json String Representation "); System.out.println(studentJson); Student anotherStudent = gson.fromJson(studentJson, Student.class); System.out.println("Custom DeSerializer : Java Object Creation"); System.out.println("Student Name "+anotherStudent.getName()); System.out.println("Student Mark "+anotherStudent.getMark()); System.out.println("Student Subject "+anotherStudent.getSubject()); System.out.println("is anotherStudent is type of Student "+(anotherStudentinstanceof Student)); } } The output of the preceding code is as follows: Custom Serializer : Json String Representation {"studentname":"Sandeep","subjecttaken":"Arithmetic","marksecured":150} Custom DeSerializer : Java Object Creation Student Name Sandeep Student Mark 150 Student Subject Arithmetic is anotherStudent is type of Student true Summary This section explains about the support of Java objects and how to implement serialization and deserialization in GSON. Resources for Article : Further resources on this subject: Play Framework: Binding and Validating Objects and Rendering JSON Output [Article] Trapping Errors by Using Built-In Objects in JavaScript Testing [Article] Class-less Objects in JavaScript [Article]
Read more
  • 0
  • 0
  • 3636

article-image-playback-audio-video-and-create-media-playback-component-using-javafx
Packt
26 Aug 2010
5 min read
Save for later

Playback Audio with Video and Create a Media Playback Component Using JavaFX

Packt
26 Aug 2010
5 min read
(For more resources on Java, see here.) Playing audio with MediaPlayer Playing audio is an important aspect of any rich client platform. One of the celebrated features of JavaFX is its ability to easily playback audio content. This recipe shows you how to create code that plays back audio resources using the MediaPlayer class. Getting ready This recipe uses classes from the Media API located in the javafx.scene.media package. As you will see in our example, using this API you are able to load, configure, and playback audio using the classes Media and MediaPlayer. For this recipe, we will build a simple audio player to illustrate the concepts presented here. Instead of using standard GUI controls, we will use button icons loaded as images. If you are not familiar with the concept of loading images, review the recipe Loading and displaying images with ImageView in the previous article. In this example we will use a JavaFX podcast from Oracle Technology Network TechCast series where Nandini Ramani discusses JavaFX. The stream can be found at http://streaming.oracle.com/ebn/podcasts/media/8576726_Nandini_Ramani_030210.mp3. How to do it... The code given next has been shortened to illustrate the essential portions involved in loading and playing an audio stream. You can get the full listing of the code in this recipe from ch05/source-code/src/media/AudioPlayerDemo.fx. def w = 400;def h = 200;var scene:Scene;def mediaSource = "http://streaming.oracle.com/ebn/podcasts/media/ 8576726_Nandini_Ramani_030210.mp3";def player = MediaPlayer {media:Media{source:mediaSource}}def controls = Group { layoutX:(w-110)/2 layoutY:(h-50)/2 effect:Reflection{ fraction:0.4 bottomOpacity:0.1 topOffset:3 } content:[ HBox{spacing:10 content:[ ImageView{id:"playCtrl" image:Image{url:"{__DIR__}play-large.png"} onMouseClicked:function(e:MouseEvent){ def playCtrl = e.source as ImageView; if(not(player.status == player.PLAYING)){ playCtrl.image = Image{url:"{__DIR__}pause-large.png"} player.play(); }else if(player.status == player.PLAYING){ playCtrl.image = Image{url:"{__DIR__}play-large.png"} player.pause(); } } } ImageView{id:"stopCtrl" image:Image{url:"{__DIR__}stop-large.png"} onMouseClicked:function(e){ def playCtrl = e.source as ImageView; if(player.status == player.PLAYING){ playCtrl.image = Image{url:"{__DIR__}play-large.png"} player.stop(); } } } ]} ]} When the variable controls is added to a scene object and the application is executed, it produces the screen shown in the following screenshot: How it works... The Media API is comprised of several components which, when put together, provides the mechanism to stream and playback the audio source. To playback audio requires two classes, including Media and MediaPlayer. Let's take a look at how these classes are used to playback audio in the previous example. The MediaPlayer—the first significant item in the code is the declaration and initialization of a MediaPlayer instance assigned to the variable player. To load the audio file, we assign an instance of Media to player.media. The Media class is used to specify the location of the audio. In our example, it is a URL that points to an MP3 file. The controls—the play, pause, and stop buttons are grouped in the Group object called controls. They are made of three separate image files: play-large.png, pause-large.png, and stop-large.png, loaded by two instances of the ImageView class. The ImageView objects serve to display the control icons and to control the playback of the audio: When the application starts, imgView displays image play-large.png. When the user clicks on the image, it invokes its action-handler function, which firsts detects the status of the MediaPlayer instance. If it is not playing, it starts playback of the audio source by calling player.play() and replaces the play-large.png with the image pause-large.png. If, however, audio is currently playing, then the audio is stopped and the image is replaced back with play-large.png. The other ImageView instance loads the stop-large.png icon. When the user clicks on it, it calls its action-handler to first stop the audio playback by calling player.stop(). Then it toggles the image for the "play" button back to icon play-large.png. As mentioned in the introduction, JavaFX will play the MP3 file format on any platform where the JavaFX format is supported. Anything other than MP3 must be supported natively by the OS's media engine where the file is played back. For instance, on my Mac OS, I can play MPEG-4, because it is a supported playback format by the OS's QuickTime engine. There's more... The Media class models the audio stream. It exposes properties to configure the location, resolves dimensions of the medium (if available; in the case of audio, that information is not available), and provides tracks and metadata about the resource to be played. The MediaPlayer class itself is a controller class responsible for controlling playback of the medium by offering control functions such as play(), pause(), and stop(). It also exposes valuable playback data including current position, volume level, and status. We will use these additional functions and properties to extend our playback capabilities in the recipe Controlling media playback in this article. See also Accessing media assets Loading and displaying images with ImageView  
Read more
  • 0
  • 0
  • 3619

article-image-embedded-linux-and-its-elements
Packt
22 Sep 2015
6 min read
Save for later

Embedded Linux and Its Elements

Packt
22 Sep 2015
6 min read
 In this article by Chris Simmonds, author of the book, Mastering Embedded Linux Programming, we'll cover the introduction of embedded Linux and its elements. (For more resources related to this topic, see here.) Why is embedded Linux popular? Linux first became a viable choice for embedded devices around 1999. That was when Axis (www.axis.com) released their first Linux-powered network camera and Tivo (www.tivo.com) their first DVR (Digital video recorder). Since 1999, Linux has become ever more popular, to the point that today it is the operating system of choice for many classes of product. As of this writing, in 2015, there are about 2 billion devices running Linux. That includes a large number of smart phones running Android, set top boxes and smart TVs and WiFi routers. Not to mention a very diverse range of devices such as vehicle diagnostics, weighing scales, industrial devices and medical monitoring units that ship in smaller volumes. So, why does your TV run Linux? At first glance, the function of a TV is simple: it has to display a stream of video on a screen. Why is a complex Unix-based operating system like Linux necessary? The simple answer is Moore's Law: Gordon Moore, co-founder of Intel stated in 1965 that the density of components on a chip will double every 2 years. That applies to the devices that we design and use in our everyday lives just as much as it does to desktops, laptops and servers. A typical SoC (System on Chip) at the heart of current devices contains many function block and has a technical reference manual that stretches to thousands of pages. Your TV is not simply displaying a video stream as the old analog sets used to. The stream is digital, possibly encrypted, and it needs processing to create an image. Your TV is (or soon will be) connected to the Internet. It can receive content from smart phones, tablets and home media servers. It can be (or soon will) used to play games. And so on and so on. You need a full operating system to manage all that hardware. Here are some points that drive the adoption of Linux: Linux has the functionality required. It has a good scheduler, a good network stack, support for many kinds of storage media, good support for multimedia devices, and so on. It ticks all the boxes. Linux has been ported to a wide range of processor architectures, including those important for embedded use: ARM, MIPS, x86 and PowerPC. Linux is open source. So you have the freedom to get the source code and modify it to meet your needs. You, or someone in the community, can create a board support package for your particular SoC, board or device. You can add protocols, features, technologies that may be missing from the mainline source code. Or, you can remove features that you don't need in order to reduce memory and storage requirements. Linux is flexible. Linux has an active community. In the case of the Linux kernel, very active. There is a new release of the kernel every 10 to 12 weeks, and each release contains code from around 1000 developers. An active community means that Linux is up to date and supports current hardware, protocols and standards. Open source licenses guarantee that you have access to the source code. There is no vendor tie-in. There is no vendor, no license fees, no restrictive NDAs, EULAs, and so on. Open source software is free in both senses: it gives you the freedom to adapt it for our own use and there is nothing to pay. For these reasons, Linux is an ideal choice for complex devices. But there are a few caveats I should mention here. Complexity makes it harder to understand. Coupled with the fast moving development process and the decentralized structures of open source, you have to put some effort into learning how to use it and to keep on re-learning as it changes. I hope that this article will help in the process. Elements of embedded Linux Every project begins by obtaining, customizing and deploying these four elements: Toolchain, Bootloader, Kernel, and Root filesystem. Toolchain The toolchain is the first element of embedded Linux and the starting point of your project. It should be constant throughout the project, in other words, once you have chosen your toolchain it is important to stick with it. Changing compilers and development libraries in an inconsistent way during a project will lead to subtle bugs. Obtaining a toolchain can be as simple as downloading and installing a package. But, the toolchain itself is a complex thing. Linux toolchains are almost always based on components from the GNU project (http://www.gnu.org). It is becoming possible to create toolchains based on LLVM/Clang (http://llvm.org). Bootloader The bootloader is the second element of Embedded Linux. It is the part that starts the system up and loads the operating system kernel. When considering which bootloader to focus on, there is one that stands out: U-Boot. In an embedded Linux system the bootloader has two main jobs: to start the system running and to load a kernel. In fact the first job is in somewhat subsidiary to the second in that it is only necessary to get as much of the system working as is necessary to load the kernel. Kernel The kernel is the third element of Embedded Linux. It is the component that is responsible for managing resources and interfacing with hardware, and so affects almost every aspect of your final software build. Usually it is tailored to your particular hardware configuration. The kernel has three main jobs to do: to manage resources, to interface to hardware, and to provide an API that offers a useful level of abstraction to user space programs, as summarized in the following diagram: Root filesystem The root filesystem is the fourth and final element of embedded Linux. The first objective is to create a minimal root filesystem that can give us a shell prompt. Then using that as a base we will add scripts to start other programs up, and to configure a network interface and user permissions. Knowing how to build the root filesystem from scratch is a useful skill. Summary In this article we briefly saw the introduction for embedded Linux and its elements. Resources for Article: Further resources on this subject: Virtualization[article] An Introduction to WEP [article] Raspberry Pi LED Blueprints [article]
Read more
  • 0
  • 0
  • 3613
article-image-openlayers-key-components
Packt
04 Feb 2015
13 min read
Save for later

OpenLayers' Key Components

Packt
04 Feb 2015
13 min read
In this article by, Thomas Gratier, Paul Spencer, and Erik Hazzard, authors of the book OpenLayers 3 Beginner's Guide, we will see the various components of OpenLayers and a short description about them. (For more resources related to this topic, see here.) The OpenLayers library provides web developers with components useful for building web mapping applications. Following the principles of object-oriented design, these components are called classes. The relationship between all the classes in the OpenLayers library is part of the deliberate design, or architecture, of the library. There are two types of relationships that we, as developers using the library, need to know about: relationships between classes and inheritance between classes. Relationships between classes describe how classes, or more specifically, instances of classes, are related to each other. There are several different conceptual ways that classes can be related, but basically a relationship between two classes implies that one of the class uses the other in some way, and often vice-versa. Inheritance between classes shows how behavior of classes, and their relationships are shared with other classes. Inheritance is really just a way of sharing common behavior between several different classes. We'll start our discussion of the key components of OpenLayers by focusing on the first of these – the relationship between classes. We'll start by looking at the Map class – ol.Map. Its all about the map Instances of the Map class are at the center of every OpenLayers application. These objects are instances of the ol.Map class and they use instances of other classes to do their job, which is to put an interactive map onto a web page. Almost every other class in the OpenLayers is related to the Map class in some direct or indirect relationship. The following diagram illustrates the direct relationships that we are most interested in: The preceding diagram shows the most important relationships between the Map class and other classes it uses to do its job. It tells us several important things: A map has 0 or 1 view instances and it uses the name view to refer to it. A view may be associated with multiple maps, however. A map may have 0 or more instances of layers managed by a Collection class and a layer may be associated with 0 or one Map class. The Map class has a member variable named layers that it uses to refer to this collection. A map may have 0 or more instances of overlays managed by a Collection class and an overlay may be associated with 0 or one Map class. The Map class has a member variable named overlays that it uses to refer to this collection. A map may have 0 or more instances of controls managed by a class called ol.Collection and controls may be associated with 0 or one Map class. The Map class has a member variable named controls that it uses to refer to this collection. A map may have 0 or more instances of interactions managed by a Collection class and an interaction may be associated with 0 or one Map class. The Map class has a member variable named interactions that it uses to refer to this collection. Although these are not the only relationships between the Map class and other classes, these are the ones we'll be working with the most. The View class (ol.View) manages information about the current position of the Map class. If you are familiar with the programming concept of MVC (Model-View-Controller), be aware that the view class is not a View in the MVC sense. It does not provide the presentation layer for the map, rather it acts more like a controller (although there is not an exact parallel because OpenLayers was not designed with MVC in mind). The Layer class (ol.layer.Base) is the base class for classes that provide data to the map to be rendered. The Overlay class (ol.Overlay) is an interactive visual element like a control, but it is tied to a specific geographic position. The Control class (ol.control.Control) is the base class for a group of classes that collectively provide the ability to a user to interact with the Map. Controls have a visible user interface element (such as a button or a form input element) with which the user interacts. The Interaction class (ol.interaction.Interaction) is the base class for a group of classes that also allow the user to interact with the map, but differ from controls in which they have no visible user interface element. For example, the DragPan interaction allows the user to click on and drag the map to pan around. Controlling the Map's view The OpenLayers view class, ol.View, represents a simple two-dimensional view of the world. It is responsible for determining where, and to some degree how, the user is looking at the world. It is responsible for managing the following information: The geographic center of the map The resolution of the map, which is to say how much of the map we can see around the center The rotation of the map Although you can create a map without a view, it won't display anything until a view is assigned to it. Every map must have a view in order to display any map data at all. However, a view may be shared between multiple instances of the Map class. This effectively synchronizes the center, resolution, and rotation of each of the maps. In this way, you can create two or more maps in different HTML containers on a web page, even showing different information, and have them look at the same world position. Changing the position of any of the maps (for instance, by dragging one) automatically updates the other maps at the same time! Displaying map content So, if the view is responsible for managing where the user is looking in the world, which component is responsible for determining what the user sees there? That's the job of layers and overlays. A layer provides access to a source of geospatial data. There are two basic kinds of layers, that is, raster and vector layers: In computer graphics, the term raster (raster graphics) refers to a digital image. In OpenLayers, a raster layer is one that displays images in your map at specific geographic locations. In computer graphics, the term vector (vector graphics) refers to images that are defined in terms of geometric shapes, such as points, lines, and polygons—or mathematic formulae such as Bézier curves. In OpenLayers, a vector layer reads geospatial data from vector data (such as a KML file) and the data can then be drawn onto the map. Layers are not the only way to display spatial information on the map. The other way is to use an overlay. We can create instances of ol.Overlay and add them to the map at specific locations. The overlay then positions its content (an HTML element) on the map at the specified location. The HTML element can then be used like any other HTML element. The most common use of overlays is to display spatially relevant information in a pop-up dialog in response to the mouse moving over, or clicking on a geographic feature. Interacting with the map As mentioned earlier, the two components that allow users to interact with the map are Interactions and Controls. Let's look at them in a bit more detail. Using interactions Interactions are components that allow the user to interact with the map via some direct input, usually by using the mouse (or a finger with a touch screen). Interactions have no visible user interface. The default set of interactions are: ol.interaction.DoubleClickZoom: If you double-click the left mouse button, the map will zoom in by a factor of 2 ol.interaction.DragPan: If you drag the map, it will pan as you move the mouse ol.interaction.PinchRotate: On touch-enabled devices, placing two fingers on the device and rotating them in a circular motion will rotate the map ol.interaction.PinchZoom: On touch-enabled devices, placing two fingers on the device and pinching them together or spreading them apart will zoom the map out and in respectively ol.interaction.KeyboardPan: You can use the arrow keys to pan the map in the direction of the arrows ol.interaction.KeyboardZoom: You can use the + and – keys to zoom in and out ol.interaction.MouseWheelZoom: You can use the scroll wheel on a mouse to zoom the map in and out ol.interaction.DragZoom: If you hold the Shift key while dragging on map, a rectangular region will be drawn and when you release the mouse button, you will zoom into that area Controls Controls are components that allow the user to modify the map state via some visible user interface element, such as a button. In the examples we've seen so far, we've seen zoom buttons in the top-left corner of the map and an attribution control in the bottom-right corner of the map. In fact, the default controls are: ol.control.Zoom: This displays the zoom buttons in the top-left corner. ol.control.Rotate: This is a button to reset rotation to 0; by default, this is only displayed when the map's rotation is not 0. Ol.control.Attribution: This displays attribution text for the layers currently visible in the map. By default, the attributions are collapsed to a single icon in the bottom-right corner and clicking the icon will show the attributions. This concludes our brief overview of the central components of an OpenLayers application. We saw that the Map class is at the center of everything and there are some key components—the view, layers, overlays, interactions, and controls—that it uses to accomplish its job of putting an interactive map onto a web page. At the beginning of this article, we talked about both relationships and inheritance. So far, we've only covered the relationships. In the next section, we'll show the inheritance architecture of the key components and introduce three classes that have been working behind the scenes to make everything work. OpenLayers' super classes In this section, we will look at three classes in the OpenLayers library that we won't often work directly with, but which provide an enormous amount of functionality to most of the other classes in the library. The first two classes, Observable and Object, are at the base of the inheritance tree for OpenLayers—the so-called super classes that most classes inherit from. The third class, Collection, isn't actually a super class but is used as the basis for many relationships between classes in OpenLayers—we've already seen that the Map class relationships with layers, overlays, interactions, and controls are managed by instances of the Collection class. Before we jump into the details, take a look at the inheritance diagram for the components we've already discussed: As you can see, the Observable class, ol.Observable, is the base class for every component of OpenLayers that we've seen so far. In fact, there are very few classes in the OpenLayers library that do not inherit from the Observable class or one of its subclasses. Similarly, the Object class, ol.Object, is the base class for many classes in the library and itself is a subclass of Observable. The Observable and Object classes aren't very glamorous. You can't see them in action and they don't do anything very exciting from a user's perspective. What they do though is provide two common sets of behavior that you can expect to be able to use on almost every object you create or access through the OpenLayers library—Event management and Key-Value Observing (KVO). Event management with the Observable class An event is basically what it sounds like—something happening. Events are a fundamental part of how various components of OpenLayers—the map, layers, controls, and pretty much everything else—communicate with each other. It is often important to know when something has happened and to react to it. One type of event that is very useful is a user-generated event, such as a mouse click or touches on a mobile device's screen. Knowing when the user has clicked and dragged on the Map class allows some code to react to this and move the map to simulate panning it. Other types of events are internal, such as the map being moved or data finishing loading. To continue the previous example, once the map has moved to simulate panning, another event is issued by OpenLayers to say that the map has finished moving so that other parts of OpenLayers can react by updating the user interface with the center coordinates or by loading more data. Key-Value Observing with the Object class OpenLayers' Object class inherits from Observable and implements a software pattern called Key-Value Observing (KVO). With KVO, an object representing some data maintains a list of other objects that wish to observe it. When the data value changes, the observers are notified automatically. Working with Collections The last section for this article is about the OpenLayers' Collection class, ol.Collection. As mentioned, the Collection class is not a super class like Observable and Object, but it is an integral part of the relationship model. Many classes in OpenLayers make use of the Collection class to manage one-to-many relationships. At its core, the Collection class is a JavaScript array with additional convenience methods. It also inherits directly from the Object class and inherits the functionality of both Observable and Object. This makes the Collection class extremely powerful. Collection properties A Collection class, inherited from the Object class, has one observable property, length. When a collection changes (elements are added or removed), it's length property is updated. This means it also emits an event, change:length, when the length property is changed. Collection events A Collection class also inherits the functionality of the Observable class (via Object class) and emits two other events—add and remove. Registered event handler functions of both events will receive a single argument, a CollectionEvent, that has an element property with the element that was added or removed. Summary This wraps up our overview of the key concepts in the OpenLayers library. We took a quick look at the key components of the library from two different aspects—relationships and inheritance. With the Map class as the central object of any OpenLayers application, we looked at its main relationships to other classes including views, layers, overlays, interactions, and controls. We briefly introduced each of these classes to give an overview of primary purpose. We then investigated inheritance related to these objects and reviewed the super classes that provide functionality to most classes in the OpenLayers library—the Observable and Object classes. The Observable class provides a basic event mechanism and the Object class adds observable properties with a powerful binding feature. Lastly, we looked at the Collection class. Although this isn't part of the inheritance structure, it is crucial to know how one-to-many relationships work throughout the library (including the Map class relationships with layers, overlays, interactions, and controls). Resources for Article: Further resources on this subject: OGC for ESRI Professionals [Article] Improving proximity filtering with KNN [Article] OpenLayers: Overview of Vector Layer [Article]
Read more
  • 0
  • 0
  • 3611

article-image-introduction-jsf-part-2
Packt
30 Dec 2009
7 min read
Save for later

An Introduction to JSF: Part 2

Packt
30 Dec 2009
7 min read
Standard JSF Validators The JSF Core tag library also includes a number of built-in validators. These validator tags can also be registered with UI components to verify that required fields are completed by the user-that numeric values are within an acceptable range,and that text values are a certain length. For more specific validation scenarios, we can also write our own custom validators. User input validation happens immediately after data conversion during the JSF request lifecycle. Validating the Length of a Text Value JSF includes a built-in validator that can be used to ensure a text value entered by the user is between an expected minimum and maximum length. The following example demonstrates using the <f:validatelength> tag’s minimum and maximum attributes to check that the password entered by the user in the password field is exactly 8 characters long. It also demonstrates how to use the label attribute of certain JSF input components (introduced in JSF 1.2) to render a localizable validation message. JSF Validation Messages The JSF framework includes predefined validation messages for different input components and validation scenarios. These messages are defined in a message bundle (properties file) including in the JSF implementation jar file. Many of these messages are parameterized, meaning that since JSF 1.2 a UI component’s label can be inserted into these messages to provide more detailed information to the user. The default JSF validation messages can be overridden by specifying the same message bundle keys in the application’s message bundle. We will see an example of customizing JSF validation messages below. Notice that we also set the maxlength attribute of the <h:inputsecret> tag to limit the input to 8 characters. This does not, however, ensure that the user enters a minimum of 8 characters. Therefore, the <f:validatelength> validator tag is required.   <f:view> <h:form> <h:outputLabel value="Please enter a password (must be 8 characters): " /> <h:inputSecret maxlength="8" id="password" value="#{backingBean.password}" label="Password"> <f:validateLength minimum="8" maximum="8" /> </h:inputSecret> <h:commandButton value="Submit" /><br /> <h:message for="password" errorStyle="color:red" /> </h:form> </f:view> Validating a Required Field The following example demonstrates how to use the built-in JSF validators to ensure that a text field is filled out before the form is processed, and that the numeric value is between 1 and 10: <f:view> <h:form> <h:outputLabel value="Please enter a number: " /> <h:inputText id="number" label="Number" value="#{backingBean.price}" required="#{true}" /> <h:commandButton value="Submit" /><br /> <h:message for="number" errorClass="error" /> </h:form> </f:view> The following screenshot demonstrates the result of submitting a JSF form containing a required field that was not filled out. We render the validation error message using an <h:message> tag with a for attribute set to the ID of the text field component. We have also overridden the default JSF validation message for required fields by specifying the following message key in our message bundle. We will discuss message bundles and internationalization (I18N) shortly.   javax.faces.component.UIInput.REQUIRED=Required field. javax.faces.component.UIInput.REQUIRED_detail=Please fill in this field. Validating a numeric range The JSF Core <f:validatelongrange> and </f:validatedoublerange> tags can be used to validate numeric user input. The following example demonstrates how to use the <f:validatelongrange> tag to ensure an integer value entered by the user is between 1 and 10. <f:view> <h:form> <h:outputLabel value="Please enter a number between 1 and 10: " /> <h:inputText id="number" value="#{backingBean.number}" label="Number"> <f:validateLongRange minimum="1" maximum="10" /> </h:inputText> <h:commandButton value="Submit" /><br /> <h:message for="number" errorStyle="color:red" /> <h:outputText value="You entered: #{backingBean.number}" rendered="#{backingBean.number ne null}" /> </h:form> </f:view> The following screenshot shows the result of entering an invalid value into the text field. Notice that the value of the text field’s label attribute is interpolated with the standard JSF validation message. Validating a floating point number is similar to validating an integer. The following example demonstrates how to use the value to ensure that a floating point number is between 0.0 and 1.0.   <f:view> <h:form> <h:outputLabel value="Please enter a floating point number between 0 and 1: " /> <h:inputText id="number" value="#{backingBean.percentage}" label="Percent"> <f:validateDoubleRange minimum="0.0" maximum="1.0" /> </h:inputText> <h:commandButton value="Submit" /><br /> <h:message for="number" errorStyle="color:red" /> <h:outputText value="You entered: " rendered="#{backingBean.percentage ne null}" /> <h:outputText value="#{backingBean.percentage}" rendered="#{backingBean.percentage ne null}" > <f:convertNumber type="percent" maxFractionDigits="2" /> </h:outputText> </h:form> </f:view> Registering a custom validator JSF also supports defining custom validation classes to provide more specialized user input validation. To create a custom validator, first we need to implement the javax.faces.validator.Validator interface. Implementing a custom validator in JSF is straightforward. In this example, we check if a date supplied by the user represents a valid birthdate. As most humans do not live more than 120 years, we reject any date that is more than 120 years ago. The important thing to note from this code example is not the validation logic itself, but what to do when the validation fails. Note that we construct a FacesMessage object with an error message and then throw a ValidatorException.   package chapter1.validator; import java.util.Calendar; import java.util.Date; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.Validator; import javax.faces.validator.ValidatorException; public class CustomDateValidator implements Validator { public void validate(FacesContext context, UIComponent component, Object object) throws ValidatorException { if (object instanceof Date) { Date date = (Date) object; Calendar calendar = Calendar.getInstance(); calendar.roll(Calendar.YEAR, -120); if (date.before(calendar.getTime())) { FacesMessage msg = new FacesMessage(); msg.setSummary("Invalid birthdate: " + date); msg.setDetail("The date entered is more than 120 years ago."); msg.setSeverity(FacesMessage.SEVERITY_ERROR); throw new ValidatorException(msg); } } } } We have to declare our custom validators in faces-config.xml as follows, giving the validator an ID of customDateValidator: <validator> <description>This birthdate validator checks a date to make sure it is within the last 120 years.</description> <display-name>Custom Date Validator</display-name> <validator-id>customDateValidator</validator-id> <validator-class> chapter1.validator.CustomDateValidator </validator-class> </validator> Next, we would register our custom validator on a JSF UI component using the tag. This tag has a converterId attribute that expects the ID of a custom converter declared in faces-config.xml. Notice in the following example that we are also registering the standard JSF <f:convertdatetime></f:convertdatetime> converter on the tag. This is to ensure that the value entered by the user is first converted to a java.util.Date object before it is passed to our custom validator. <h:inputText id="name" value="#{backingBean.date}"> <f:convertDateTime type="date" pattern="M/d/yyyy" /> <f:validator validatorId="customDateValidator" /> </h:inputText> Many JSF UI component tags have both a converter and validator attribute that accept EL method expressions. These attributes provides another way to register custom converters and validators implemented in managed beans on UI components.
Read more
  • 0
  • 0
  • 3604
Modal Close icon
Modal Close icon