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
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-python-libraries-geospatial-development
Packt
17 Jun 2013
14 min read
Save for later

Python Libraries for Geospatial Development

Packt
17 Jun 2013
14 min read
(For more resources related to this topic, see here.) Reading and writing geospatial data While you could in theory write your own parser to read a particular geospatial data format, it is much easier to use an existing Python library to do this. We will look at two popular libraries for reading and writing geospatial data: GDAL and OGR. GDAL/OGR Unfortunately, the naming of these two libraries is rather confusing. Geospatial Data Abstraction Library ( GDAL), was originally just a library for working with raster geospatial data, while the separate OGR library was intended to work with vector data. However, the two libraries are now partially merged, and are generally downloaded and installed together under the combined name of "GDAL". To avoid confusion, we will call this combined library GDAL/OGR and use "GDAL" to refer to just the raster translation library. A default installation of GDAL supports reading 116 different raster file formats, and writing to 58 different formats. OGR by default supports reading 56 different vector file formats, and writing to 30 formats. This makes GDAL/OGR one of the most powerful geospatial data translators available, and certainly the most useful freely-available library for reading and writing geospatial data. GDAL design GDAL uses the following data model for describing raster geospatial data: Let's take a look at the various parts of this model: A dataset holds all the raster data, in the form of a collection of raster "bands", along with information that is common to all these bands. A dataset normally represents the contents of a single file. A raster band represents a band, channel, or layer within the image. For example, RGB image data would normally have separate bands for the red, green, and blue components of the image. The raster size specifies the overall width and height of the image, in pixels. The georeferencing transform converts from (x, y) raster coordinates into georeferenced coordinates—that is, coordinates on the surface of the earth. There are two types of georeferencing transforms supported by GDAL: affine transformations and ground control points. An affine transformation is a mathematical formula allowing the following operations to be applied to the raster data: More than one of these operations can be applied at once; this allows you to perform sophisticated transforms such as rotations. Affine transformations are sometimes referred to as linear transformations. Ground Control Points ( GCPs) relate one or more positions within the raster to their equivalent georeferenced coordinates, as shown in the following figure: Note that GDAL does not translate coordinates using GCPs— that is left up to the application, and generally involves complex mathematical functions to perform the transformation. The coordinate system describes the georeferenced coordinates produced the georeferencing transform. The coordinate system includes the projection and datum, as well as the units and scale used by the raster data. The metadata contains additional information about the dataset as a whole. Each raster band contains the following (among other things): The band raster size: This is the size (number of pixels across and number of lines high) for the data within the band. This may be the same as the raster size for the overall dataset, in which case the dataset is at full resolution, or the band's data may need to be scaled to match the dataset. Some band metadata providing extra information specific to this band. A color table describing how pixel values are translated into colors. The raster data itself. GDAL provides a number of drivers which allow you to read (and sometimes write) various types of raster geospatial data. When reading a file, GDAL selects a suitable driver automatically based on the type of data; when writing, you first select the driver and then tell the driver to create the new dataset you want to write to. GDAL example code A Digital Elevation Model ( DEM) file contains height values. In the following example program, we use GDAL to calculate the average of the height values contained in a sample DEM file. In this case, we use a DEM file downloaded from the GLOBE elevation dataset: from osgeo import gdal,gdalconst import struct dataset = gdal.Open("data/e10g") band = dataset.GetRasterBand(1) fmt = "<" + ("h" * band.XSize) totHeight = 0 for y in range(band.YSize): scanline = band.ReadRaster(0, y, band.XSize, 1, band.XSize, 1, band.DataType) values = struct.unpack(fmt, scanline) for value in values: if value == -500: # Special height value for the sea -> ignore. continue totHeight = totHeight + value average = totHeight / (band.XSize * band.YSize) print "Average height =", average As you can see, this program obtains the single raster band from the DEM file, and then reads through it one scanline at a time. We then use the struct standard Python library module to read the individual height values out of the scanline. Because the GLOBE dataset uses a special height value of -500 to represent the ocean, we exclude these values from our calculations. Finally, we use the remaining height values to calculate the average height, in meters, over the entire DEM data file. OGR design OGR uses the following model for working with vector-based geospatial data: Let's take a look at this design in more detail: The data source represents the file you are working with—though it doesn't have to be a file. It could just as easily be a URL or some other source of data. The data source has one or more layers , representing sets of related data. For example, a single data source representing a country may contain a "terrain" layer, a "contour lines" layer, a "roads" later, and a "city boundaries" layer. Other data sources may consist of just one layer. Each layer has a spatial reference and a list of features. The spatial reference specifies the projection and datum used by the layer's data. A feature corresponds to some significant element within the layer. For example, a feature might represent a state, a city, a road, an island, and so on. Each feature has a list of attributes and a geometry. The attributes provide additional meta-information about the feature. For example, an attribute might provide the name for a city's feature, its population, or the feature's unique ID used to retrieve additional information about the feature from an external database. Finally, the geometry describes the physical shape or location of the feature. Geometries are recursive data structures that can themselves contain sub-geometries—for example, a "country" feature might consist of a geometry that encompasses several islands, each represented by a subgeometry within the main "country" geometry. The geometry design within OGR is based on the Open Geospatial Consortium's "Simple Features" model for representing geospatial geometries. For more information, see http://www.opengeospatial.org/standards/sfa . Like GDAL, OGR also provides a number of drivers which allow you to read (and sometimes write) various types of vector-based geospatial data. When reading a file, OGR selects a suitable driver automatically; when writing, you first select the driver and then tell the driver to create the new data source to write to. OGR example code The following example program uses OGR to read through the contents of a shapefile, printing out the value of the NAME attribute for each feature along with the geometry type: from osgeo import ogr shapefile = ogr.Open("TM_WORLD_BORDERS-0.3.shp") layer = shapefile.GetLayer(0) for i in range(layer.GetFeatureCount()): feature = layer.GetFeature(i) name = feature.GetField("NAME") geometry = feature.GetGeometryRef() print i, name, geometry.GetGeometryName() Documentation GDAL and OGR are well documented, but with a catch for Python programmers. The GDAL/OGR library and associated command-line tools are all written in C and C++. Bindings are available which allow access from a variety of other languages, including Python, but the documentation is all written for the C++ version of the libraries. This can make reading the documentation rather challenging—not only are all the method signatures written in C++, but the Python bindings have changed many of the method and class names to make them more "pythonic". Fortunately, the Python libraries are largely self-documenting, thanks to all the docstrings embedded in the Python bindings themselves. This means you can explore the documentation using tools such as Python's built-in pydoc utility, which can be run from the command line like this: % pydoc -g osgeo This will open up a GUI window allowing you to read the documentation using a web browser. Alternatively, if you want to find out about a single method or class, you can use Python's built-in help() command from the Python command line, like this: >>> import osgeo.ogr >>> help(osgeo.ogr.DataSource.CopyLayer) Not all the methods are documented, so you may need to refer to the C++ docs on the GDAL website for more information, and some of the docstrings are copied directly from the C++ documentation—but in general the documentation for GDAL/OGR is excellent, and should allow you to quickly come up to speed using this library. Availability GDAL/OGR runs on modern Unix machines, including Linux and Mac OS X, as well as most versions of Microsoft Windows. The main website for GDAL can be found at: http://gdal.org The main website for OGR is at: http://gdal.org/ogr To download GDAL/OGR, follow the Downloads link on the main GDAL website. Windows users may find the FWTools package useful, as it provides a wide range of geospatial software for win32 machines, including GDAL/OGR and its Python bindings. FWTools can be found at: http://fwtools.maptools.org For those running Mac OS X, prebuilt binaries can be obtained from: http://www.kyngchaos.com/software/frameworks Make sure that you install GDAL Version 1.9 or later, as you will need this version to work through the examples in this book. Being an open source package, the complete source code for GDAL/OGR is available from the website, so you can compile it yourself. Most people, however, will simply want to use a prebuilt binary version. Dealing with projections One of the challenges of working with geospatial data is that geodetic locations (points on the Earth's surface) are mapped into a two-dimensional Cartesian plane using a cartographic projection. Whenever you have some geospatial data, you need to know which projection that data uses. You also need to know the datum (model of the Earth's shape) assumed by the data. A common challenge when dealing with geospatial data is that you have to convert data from one projection/datum to another. Fortunately, there is a Python library pyproj which makes this task easy. pyproj pyproj is a Python "wrapper" around another library called PROJ.4. "PROJ.4" is an abbreviation for Version 4 of the PROJ library. PROJ was originally written by the US Geological Survey for dealing with map projections, and has been widely used in geospatial software for many years. The pyproj library makes it possible to access the functionality of PROJ.4 from within your Python programs. Design The pyproj library consists of the following pieces: pyproj consists of just two classes: Proj and Geod. Proj converts from longitude and latitude values to native map (x, y) coordinates, and vice versa. Geod performs various Great Circle distance and angle calculations. Both are built on top of the PROJ.4 library. Let's take a closer look at these two classes. Proj Proj is a cartographic transformation class, allowing you to convert geographic coordinates (that is, latitude and longitude values) into cartographic coordinates (x, y values, by default in meters) and vice versa. When you create a new Proj instance, you specify the projection, datum, and other values used to describe how the projection is to be done. For example, to use the Transverse Mercator projection and the WGS84 ellipsoid, you would do the following: projection = pyproj.Proj(proj='tmerc', ellps='WGS84') Once you have created a Proj instance, you can use it to convert a latitude and longitude to an (x, y) coordinate using the given projection. You can also use it to do an inverse projection—that is, converting from an (x, y) coordinate back into a latitude and longitude value again. The helpful transform() function can be used to directly convert coordinates from one projection to another. You simply provide the starting coordinates, the Proj object that describes the starting coordinates' projection, and the desired ending projection. This can be very useful when converting coordinates, either singly or en masse. Geod Geod is a geodetic computation class, which allows you to perform various Great Circle calculations. We looked at Great Circle calculations earlier, when considering how to accurately calculate the distance between two points on the Earth's surface. The Geod class, however, can do more than this: The fwd() method takes a starting point, an azimuth (angular direction) and a distance, and returns the ending point and the back azimuth (the angle from the end point back to the start point again):   The inv() method takes two coordinates and returns the forward and back azimuth as well as the distance between them:   The npts() method calculates the coordinates of a number of points spaced equidistantly along a geodesic line running from the start to the end point:   When you create a new Geod object, you specify the ellipsoid to use when performing the geodetic calculations. The ellipsoid can be selected from a number of predefined ellipsoids, or you can enter the parameters for the ellipsoid (equatorial radius, polar radius, and so on) directly. Example code The following example starts with a location specified using UTM zone 17 coordinates. Using two Proj objects to define the UTM Zone 17 and lat/long projections, it translates this location's coordinates into latitude and longitude values: import pyproj UTM_X = 565718.5235 UTM_Y = 3980998.9244 srcProj = pyproj.Proj(proj="utm", zone="11", ellps="clrk66", units="m") dstProj = pyproj.Proj(proj="longlat", ellps="WGS84", datum="WGS84") long,lat = pyproj.transform(srcProj, dstProj, UTM_X, UTM_Y) print "UTM zone 11 coordinate (%0.4f, %0.4f) = %0.4f, %0.4f" % (UTM_X, UTM_Y, lat, long) Continuing on with this example, let's take the calculated lat/long values and, using a Geod object, calculate another point 10 kilometers northeast of that location: angle = 315 # 315 degrees = northeast. distance = 10000 geod = pyproj.Geod(ellps="WGS84") long2,lat2,invAngle = geod.fwd(long, lat, angle, distance) print "%0.4f, %0.4f is 10km northeast of %0.4f, %0.4f" % (lat2, long2, lat, long) Documentation The documentation available on the pyproj website, and in the docs directory provided with the source code, is excellent as far as it goes. It describes how to use the various classes and methods, what they do and what parameters are required. However, the documentation is rather sparse when it comes to the parameters used when creating a new Proj object. As the documentation says: A Proj class instance is initialized with proj map projection control parameter key/value pairs. The key/value pairs can either be passed in a dictionary, or as keyword arguments, or as a proj4 string (compatible with the proj command). The documentation does provide a link to a website listing a number of standard map projections and their associated parameters, but understanding what these parameters mean generally requires you to delve into the PROJ documentation itself. The documentation for PROJ is dense and confusing, even more so because the main manual is written for PROJ Version 3, with addendums for later versions. Attempting to make sense of all this can be quite challenging. Fortunately, in most cases you won't need to refer to the PROJ documentation at all. When working with geospatial data using GDAL or OGR, you can easily extract the projection as a "proj4 string" which can be passed directly to the Proj initializer. If you want to hardwire the projection, you can generally choose a projection and ellipsoid using the proj="..." and ellps="..." parameters, respectively. If you want to do more than this, though, you will need to refer to the PROJ documentation for more details. To find out more about PROJ, and to read the original documentation, you can find everything you need at: http://trac.osgeo.org/proj
Read more
  • 0
  • 0
  • 8088

article-image-apache-cloudstack-architecture
Packt
17 Jun 2013
17 min read
Save for later

Apache CloudStack Architecture

Packt
17 Jun 2013
17 min read
(For more resources related to this topic, see here.) Introducing cloud Before embarking on a journey to understand and appreciate CloudStack, let's revisit the basic concepts of cloud computing and how CloudStack can help us in achieving our private, public, or hybrid cloud objectives. Let's start this article with a plain and simple definition of cloud. Cloud is a shared multi-tenant environment built on a highly efficient, highly automated, and preferably virtualized IT infrastructure where IT resources can be provisioned on demand from anywhere over a broad network, and can be metered. Virtualization is the technology that has made the enablement of these features simpler and convenient. A cloud can be deployed in various models; including private, public, community or hybrid clouds. These deployment models can be explained as follows: Private cloud: In this deployment model, the cloud infrastructure is operated solely for an organization and may exist on premise or off premise. It can be managed by the organization or a third-party cloud provider. Public cloud: In this deployment model, the cloud service is provided to the general public or a large industry group, and is owned and managed by the organization providing cloud services. Community cloud: In this deployment model, the cloud is shared by multiple organizations and is supported by a specific community that has shared concerns. It can be managed by the organization or a third party provider, and can exist on premise or off premise. Hybrid cloud: This deployment model comprises two or more types of cloud (public, private, or community) and enables data and application portability between the clouds. A cloud—be it private, public, or hybrid—has the following essential characteristics: On-demand self service Broad network access Resource pooling Rapid elasticity or expansion Measured service Shared by multiple tenants Cloud has three possible service models, which means there are three types of cloud services that can be provided. They are: Infrastructure as a service (IaaS): This type of cloud service model provides IT infrastructure resources as a service to the end users. This model provides the end users with the capability to provision processing, storage, networks, and other fundamental computing resources that the customer can use to run arbitrary software including operating systems and applications. The provider manages and controls the underlying cloud infrastructure and the user has control over the operating systems, storage and deployed applications. The user may also have some control over the networking services. Platform as a service (PaaS): In this service model, the end user is provided with a platform that is provisioned over the cloud infrastructure. The provider manages the network, operating system, or storage and the end user has control over the applications and may have control over the hosting environment of the applications. Software as a service (SaaS): This layer provides software as a service to the end users, such as providing an online calculation engine for their end users. The end users can access these software using a thin client interface such as a web browser. The end users do not manage the underlying cloud infrastructure such as network, servers, OS, storage, or even individual application capabilities but may have some control over the application configurations settings. As depicted in the preceding diagram, the top layers of cloud computing are built upon the layer below it. In this book, we will be mainly dealing with the bottom layer—Infrastructure as a service. Thus providing Infrastructure as a Service essentially means that the cloud provider assembles the building blocks for providing these services, including the computing resources hardware, networking hardware and storage hardware. These resources are exposed to the consumers through a request management system which in turn is integrated with an automated provisioning layer. The cloud system also needs to meter and bill the customer on various chargeback models. The concept of virtualization enables the provider to leverage and pool resources in a multi-tenant model. Thus, the features provided by virtualization resource pooling, combined with modern clustering infrastructure, enable efficient use IT resources to provide high availability and scalability, increase agility, optimize utilization, and provide a multi-tenancy model. One can easily get confused about the differences between the cloud and a virtualized Datacenter; well, there are many differences, such as: The cloud is the next stage after the virtualization of datacenters. It is characterized by a service layer over the virtualization layer. Instead of bare computing resources, services are built over the virtualization platforms and provided to the users. Cloud computing provides the request management layer, provisioning layer, metering and billing layers along with security controls and multi-tenancy. Cloud resources are available to consumers on an on demand model wherein the resources can be provisioned and de-provisioned on an as needed basis. Cloud providers typically have huge capacities to serve variable workloads and manage variable demand from customers. Customers can leverage the scaling capabilities provided by cloud providers to scale up or scale down the IT infrastructure needed by the application and the workload. This rapid scaling helps the customer save money by using the capacity only when it is needed. The resource provisioning in the cloud is governed by policies and rules, and the process of provisioning is automated. Metering, Chargeback, and Billing are essential governance characteristics of any cloud environment as they govern and control the usage of precious IT resources. Thus setting up a cloud is basically building capabilities to provide IT resources as a service in a well-defined manner. Services can be provided to end users in various offerings, depending upon the amount of resources each service offering provides. The amount of resources can be broken down to multiple resources such as the computing capacity, memory, storage, network bandwidth, storage IOPS, and so on. A cloud provider can provide and meter multiple service offerings for the end users to choose from. Though the cloud provider makes upfront investments in creating the cloud capacity, however from a consumer's point of view the resources are available on demand on a pay per use model. Thus the customer gets billed for consumption just like in case of electricity or telecom services that individuals use. The billing may be based on hours of compute usage, the amount of storage used, bandwidth consumed, and so on. Having understood the cloud computing model, let's look at the architecture of a typical Infrastructure as a Service cloud environment. Infrastructure layer The Infrastructure layer is the base layer and comprises of all the hardware resources upon which IT is built upon. These include computing resources, storage resources, network resources, and so on. Computing resources Virtualization is provided using a hypervisor that has various functions such as enabling the virtual machines of the hosts to interact with the hardware. The physical servers host the hypervisor layer. The physical server resources are accessed through the hypervisor. The hypervisor layer also enables access to the network and storage. There are various hypervisors on the market such as VMware, Hyper-V, XenServer, and so on. These hypervisors are responsible for making it possible for one physical server to host multiple machines, and for enabling resource pooling and multi tenancy. Storage Like the Compute capacity, we need storage which is accessible to the Compute layer. The Storage in cloud environments is pooled just like the Compute and accessed through the virtualization layer. Certain types of services just offer storage as a service where the storage can be programmatically accessed to store and retrieve objects. Pooled, virtualized storage is enabled through technologies such as Network Attached Storage (NAS) and Storage Area Network (SAN) which helps in allowing the infrastructure to allocate storage on demand that can be based on policy, that is, automated. The storage provisioning using such technologies helps in providing storage capacity on demand to users and also enables the addition or removal of capacity as per the demand. The cost of storage can be differentiated according to the different levels of performance and classes of storage. Typically, SAN is used for storage capacity in the cloud where statefulness is required. Direct-attached Storage (DAS) can be used for stateless workloads that can drive down the cost of service. The storage involved in cloud architecture can be redundant and prevent the single point of failure. There can be multiple paths for the access of disk arrays to provide redundancy in case connectivity failures. The storage arrays can also be configured in a way that there is incremental backup of the allocated storage. The storage should be configured such that health information of the storage units is updated in the system monitoring service, which ensures that the outage and its impact are quickly identified and appropriate action can be taken in order to restore it to its normal state. Networks and security Network configuration includes defining the subnets, on-demand allocation of IP addresses, and defining the network routing tables to enable the flow of data in the network. It also includes enabling high availability services such as load balancing. Whereas the security configuration aims to secure the data flowing in the network that includes isolation of data of different tenants among each other and with the management data of cloud using techniques such as network isolation and security groups. Networking in the cloud is supposed to deal with the isolation of resources between multiple tenants as well as provide tenants with the ability to create isolated components. Network isolation in the cloud can be done using various techniques of network isolation such as VLAN, VXLAN, VCDNI, STT, or other such techniques. Applications are deployed in a multi-tenant environment and consist of components that are to be kept private, such as a database server which is to be accessed only from selected web servers and any other traffic from any other source is not permitted to access it. This is enabled using network isolation, port filtering, and security groups. These services help with segmenting and protecting various layers of application deployment architecture and also allow isolation of tenants from each other. The provider can use security domains, layer 3 isolation techniques to group various virtual machines. The access to these domains can be controlled using providers' port filtering capabilities or by the usage of more stateful packet filtering by implementing context switches or firewall appliances. Using network isolation techniques such as VLAN tagging and security groups allows such configuration. Various levels of virtual switches can be configured in the cloud for providing isolation to the different networks in the cloud environment. Networking services such as NAT, gateway, VPN, Port forwarding, IPAM systems, and access control management are used in the cloud to provide various networking services and accessibility. Some of these services are explained as follows: NAT: Network address translation can be configured in the environment to allow communication of a virtual machine in private network with some other machine on some other network or on the public Internet. A NAT device allows the modification of IP address information in the headers of IP packets while they are transformed from a routing device. A machine in a private network cannot have direct access to the public network so in order for it to communicate to the Internet, the packets are sent to a routing device or a virtual machine with NAT configured which has direct access to the Internet. NAT modifies the IP packet header so that the private IP address of the machine is not visible to the external networks. IPAM System/DHCP: An IP address management system or DHCP server helps with the automatic configuration of IP addresses to the virtual machines according to the configuration of the network and the IP range allocated to it. A virtual machine provisioned in a network can be assigned an IP address as per the user or is assigned an IP address from the IPAM. IPAM stores all the available IP addresses in the network and when a new IP address is to be allocated to a device, it is taken from the available IP pool, and when a device is terminated or releases the IP address, the address is given back to the IPAM system. Identity and access management: A access control list describes the permissions of various users on different resources in the cloud. It is important to define an access control list for users in a multi-tenant environment. It helps in restricting actions that a user can perform on any resource in the cloud. A role-based access mechanism is used to assign roles to users' profile which describes the roles and permissions of users on different resources. Use of switches in cloud A switch is a LAN device that works at the data link layer (layer 2) of the OSI model and provides multiport bridge. Switches store a table of MAC addresses and ports. Let us see the various types of switches and their usage in the cloud environment: Layer 3 switches: A layer-3 switch is a special type of switch which operates at layer 3—the Network layer of the OSI model. It is a high performance device that is used for network routing. A layer-3 switch has a IP routing table for lookups and it also forms a broadcast domain. Basically, a layer-3 switch is a switch which has a router's IP routing functionality built in. A layer-3 switch is used for routing and is used for better performance over routers. The layer-3 switches are used in large networks like corporate networks instead of routers. The performance of the layer-3 switch is better than that of a router because of some hardware-level differences. It supports the same routing protocols as network routers do. The layer-3 switch is used above the layer-2 switches and can be used to configure the routing configuration and the communication between two different VLANs or different subnets. Layer 4-7 switches: These switches use the packet information up to OSI layer 7 and are also known as content switches, web-switches, or application switches. These types of switches are typically used for load balancing among a group of servers which can be performed on HTTP, HTTPS, VPN, or any TCP/IP traffic using a specific port. These switches are used in the cloud for allowing policy-based switching—to limit the different amount of traffic on specific end-user switch ports. It can also be used for prioritizing the traffic of specific applications. These switches also provide forwarding decision making like NAT services and also manages the state of individual sessions from beginning to end thus acting like firewalls. In addition, these switches are used for balancing traffic across a cluster of servers as per the configuration of the individual session information and status. Hence these types of switches are used above layer-3 switches or above a cluster of servers in the environment. They can be used to forward packets as per the configuration such as transferring the packets to a server that is supposed to handle the requests and this packet forwarding configuration is generally based on the current server loads or sticky bits that binds the session to a particular server. Layer-3 traffic isolation provides traffic isolation across layer-3 devices. It's referred to as Virtual Routing and Forwarding (VRF). It virtualizes the routing table in a layer-3 switch and has set of virtualized tables for routing. Each table has a unique set of forwarding entries. Whenever traffic enters, it is forwarded using the routing table associated with the same VRF. It enables logical isolation of traffic as it crosses a common physical network infrastructure. VRFs provide access control, path isolation, and shared services. Security groups are also an example of layer-3 isolation capabilities which restricts the traffic to the guests based on the rules defined. The rules are defined based on the port, protocol, and source/destination of the traffic. Virtual switches: The virtual switches are software program that allows one guest VM to communicate with another and is similar to the Ethernet switch explained earlier. Virtual switches provide a bridge between the virtual NICs of the guest VMs and the physical NIC of the host. Virtual switches have port groups on one side which may or may not be connected to the different subnets. There are various types of virtual switches used with various virtualization technologies such as VMware Vswitch, Xen, or Open Vswitch. VMware also provides a distributed virtual switch which spans multiple hosts. The virtual switches consists of port groups at one end and an uplink at the other. The port groups are connected to the virtual machines and the uplink is mapped to the physical NIC of the host. The virtual switches function as a virtual switch over the hypervisor layer on the host. Management layer The Management layer in a cloud computing space provides management capabilities to manage the cloud setup. It provides features and functions such as reporting, configuration for the automation of tasks, configuration of parameters for the cloud setup, patching, and monitoring of the cloud components. Automation The cloud is a highly automated environment and all tasks such as provisioning the virtual machine, allocation of resources, networking, and security are done in a self-service mode through automated systems. The automation layer in cloud management software is typically exposed through APIs. The APIs allow the creation of SDKs, scripts, and user interfaces. Orchestration The Orchestration layer is the most critical interface between the IT organization and its infrastructure, and helps in the integration of the various pieces of software in the cloud computing platform. Orchestration is used to join together various individual tasks which are executed in a specified sequence with exception handling features. Thus a provisioning task for a virtual machine may involve various commands or scripts to be executed. The orchestration engine binds these individual tasks together and creates a provisioning workflow which may involve provisioning a virtual machine, adding it to your DNS, assigning IP Addresses, adding entries in your firewall and load balancer, and so on. The orchestration engine acts as an integration engine and also provides the capabilities to run an automated workflow through various subsystems. As an example, the service request to provision cloud resources may be sent to an orchestration engine which then talks to the cloud capacity layer to determine the best host or cluster where the workload can be provisioned. As a next step, the orchestration engine chooses the component to call to provision the resources. The orchestration platform helps in easy creation of complex workflows and also provides ease of management since all integrations are handled by a specialized orchestration engine and provide loose coupling. The orchestration engine is executed in the cloud system as an asynchronous job scheduler which orchestrates the service APIs to fulfill and execute a process. Task Execution The Task execution layer is at the lower level of the management operations that are performed using the command line or any other interface. The implementation of this layer can vary as per the platform on which the execution takes place. The activity of this layer is activated by the layers above in the management layer. Service Management The Service Management layer helps in compliance and provides means to implement automation and adapts IT service management best practices as per the policies of the organization, such as the IT Infrastructure Library (ITIL). This is used to build processes to implement different types of incident resolutions and also provide change management. The self service capability in cloud environment helps in providing users with a self-service catalog which consists of various service options that the user can request and provision resources from the cloud. The service layer can be comprised of various levels of services such as basic provisioning of virtual machines with some predefined templates/configuration, or can be of an advanced level with various options for provisioning servers with configuration options as well.
Read more
  • 0
  • 0
  • 8772

article-image-getting-started-leaflet
Packt
14 Jun 2013
9 min read
Save for later

Getting started with Leaflet

Packt
14 Jun 2013
9 min read
(For more resources related to this topic, see here.) Getting ready First, we need to get an Internet browser, if we don't have one already installed. Leaflet is tested with modern desktop browsers: Chrome, Firefox, Safari 5+, Opera 11.11+, and Internet Explorer 7-10. Internet Explorer 6 support is stated as not perfect but accessible. We can pick one of them, or all of them if we want to be thorough. Then, we need an editor. Editors come in many shapes and flavors: free or not free, with or without syntax highlighting, or remote file editing. A quick search on the Internet will provide thousands of capable editors. Notepad++ (http://notepad-plus-plus.org/) for Windows, Komodo Edit (http://www.activestate.com/komodo-edit) for Mac OS, or Vim (http://www.vim.org/) for Linux are among them. We can download Leaflet's latest stable release (v0.5.1 at the time of writing) and extract the content of the ZIP file somewhere appropriate. The ZIP file contains the sources as well as a prebuilt version of the library that can be found in the dist directory. Optionally, we can build from the sources included in the ZIP file; see this article's Building Leaflet from source section. Finally, let's create a new project directory on our hard drive and copy the dist folder from the extracted Leaflet package to it, ensuring we rename it to leaflet. How to do it... Note that the following code will constitute our code base throughout the rest of the article. Create a blank HTML file called index.html in the root of our project directory. Add the code given here and use the browser installed previously to execute it: <!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" href="leaflet/ leaflet.css" /> <!--[if lte IE 8]> <link rel="stylesheet" type="text/css" href=" leaflet/ leaflet.ie.css" /> <![endif]--> <script src = "leaflet/leaflet.js"></script> <style> html, body, #map { height: 100%; } body { padding: 0; margin: 0; } </style> <title>Getting Started with Leaflet</title> </head> <body> <div id="map"></div> <script type="text/javascript"> var map = L.map('map', { center: [52.48626, -1.89042], zoom: 14 }); L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/ {x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); </script> </body> </html> The following screenshot is of the first map we have created: How it works... The index.html file we created is a standardized file that all Internet browsers can read and display the contents. Our file is based on the HTML doctype standard produced by the World Wide Web Consortium (W3C), which is only one of many that can be used as seen at http://www.w3.org/QA/2002/04/valid-dtd-list.html. Our index file specifies the doctype on the first line of code as required by the W3C, using the <!DOCTYPE HTML> markup. We added a link to Leaflet's main CSS file in the head section of our code: <link rel="stylesheet" type="text/css" href="leaflet/leaflet.css" /> We also added a conditional statement to link an Internet Explorer 8 or lower only stylesheet when these browsers interpret the HTML code: <!--[if lte IE 8]> <link rel="stylesheet" type="text/css" href="leaflet/leaflet.ie.css" /> <![endif]--> This stylesheet mainly addresses Internet Explorer specific issues with borders and margins. Leaflet's JavaScript file is then referred to using a script tag: <script src = "leaflet/leaflet.js"></script> We are using the compressed JavaScript file that is appropriate for production but very inefficient for debugging. In the compressed version, every white space character has been removed, as shown in the following bullet list, which is a straight copy-paste from the source of both files for the function onMouseClick: compressed: _onMouseClick:function(t){!this._loaded||this.dragging&& this.dragging.moved()||(this.fire("preclick"),this._ fireMouseEvent(t))}, uncompressed: _onMouseClick: function (e) { if (!this._loaded || (this.dragging && this.dragging.moved())) { return; } this.fire('preclick'); this._fireMouseEvent(e); }, To make things easier, we can replace leaflet.js with leaflet-src.js—an uncompressed version of the library. We also added styles to our document to make the map fit nicely in our browser window: html, body, #map { height: 100%; } body { padding: 0; margin: 0; } The <div> tag with the id attribute map in the document's body is the container of our map. It must be given a height otherwise the map won't be displayed: <div id="map" style="height: 100%;" ></div> Finally, we added a script section enclosing the map's initialization code, instantiating a Map object using the L.map(…) constructor and a TileLayer object using the L.tileLayer(…) constructor. The script section must be placed after the map container declaration otherwise Leaflet will be referencing an element that does not yet exist when the page loads. When instantiating a Map object, we pass the id of the container of our map and an array of Map options: var map = L.map('map', { center: [52.48626, -1.89042], zoom: 14 }); There are a number of Map options affecting the state, the interactions, the navigation, and the controls of the map. See the documentation to explore those in detail at http://leafletjs.com/reference.html#map-options. Next, we instantiated a TileLayer object using the L.tileLayer(…) constructor and added to the map using the TileLayer.addTo(…) method: L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); Here, the first parameter is the URL template of our tile provider—that is OpenStreetMap— and the second a noncompulsory array of TileLayer options including the recommended attribution text for our map tile's source. The TileLayer options are also numerous. Refer to the documentation for the exhaustive list at http://leafletjs.com/reference.html#tilelayer-options. There's more... Let's have a look at some of the Map options, as well as how to build Leaflet from source or use different tile providers. More on Map options We have encountered a few Map options in the code for this recipe, namely center and zoom. We could have instantiated our OpenStreetMap TileLayer object before our Map object and passed it as a Map option using the layers option. We also could have specified a minimum and maximum zoom or bounds to our map, using minZoom and maxZoom (integers) and maxBounds, respectively. The latter must be an instance of LatLngBounds: var bounds = L.latLngBounds([ L.latLng([52.312, -2.186]), L.latLng([52.663, -1.594]) ]); We also came across the TileLayer URL template that will be used to fetch the tile images, replacing { s} by a subdomain and { x}, {y}, and {z} by the tiles coordinate and zoom. The subdomains can be configured by setting the subdomains property of a TileLayer object instance. Finally, the attribution property was set to display the owner of the copyright of the data and/or a description. Building Leaflet from source A Leaflet release comes with the source code that we can build using Node.js. This will be a necessity if we want to fix annoying bugs or add awesome new features. The source code itself can be found in the src directory of the extracted release ZIP file. Feel free to explore and look at how things get done within a Leaflet. First things first, go to http://nodejs.org and get the install file for your platform. It will install Node.js along with npm, a command line utility that will download and install Node Packaged Modules and resolve their dependencies for us. Following is the list of modules we are going to install: Jake: A JavaScript build program similar to make JSHint: It will detect potential problems and errors in JavaScript code UglifyJS: A mangler and compressor library for JavaScript Hopefully, we won't need to delve into the specifics of these tools to build Leaflet from source. So let's open a command line interpreter— cmd.exe on Windows, or a terminal on Mac OSX or Linux—and navigate to the Leaflet's src directory using the cd command, then use npm to install Jake, JSHint and UglifyJS: cd leaflet/src npm install –g jake npm install jshint npm install uglify-js We can now run Jake in Leaflet's directory: jake What about tile providers? We could have chosen a different tile provider as OpenStreetMap is free of charge but has its limitations in regard of a production environment. A number of web services provide tiles but might come at a price depending on your usage: CloudMade, MapQuest. These three providers serve tiles use the OpenStreetMap tile scheme described at http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames. Remember the way we added the OpenStreetMap layer to the map? L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); Remember the way we added the OpenStreetMap layer to the map? Cloudmade: L.tileLayer(' http://{s}.tile.cloudmade.com/API-key/997/256/{z}/ {x}/{y}.png', { attribution: ' Map data © <a href="http://openstreetmap. org">OpenStreetMap</a> contributors, <a href="http:// creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>' }).addTo(map); MapQuest: L.tileLayer('http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}. png', { attribution: ' Tiles Courtesy of <a href="http://www.mapquest. com/" target="_blank">MapQuest</a> <img src = "http://developer.mapquest.com/content/osm/mq_logo.png">', subdomains: ['otile1', 'otile2', 'otile3', 'otile4'] }).addTo(map); You will learn more about the Layer URL template and subdomains option in the documentation at http://leafletjs.com/reference.html#tilelayer. Leaflet also supports Web Map Service (WMS) tile layers—read more about it at http://leafletjs.com/reference.html#tilelayer-wms—and GeoJSON layers in the documentation at http://leafletjs.com/reference.html#geojson. Summary In this article we have learned how to create map using Leaflet and created our first map. We learned about different map options and also how to build a leaflet from source. Resources for Article : Further resources on this subject: Using JavaScript Effects with Joomla! [Article] Getting Started with OpenStreetMap [Article] Quick start [Article]
Read more
  • 0
  • 0
  • 4041

article-image-so-what-kineticjs
Packt
14 Jun 2013
3 min read
Save for later

So, what is KineticJS?

Packt
14 Jun 2013
3 min read
(For more resources related to this topic, see here.) With KineticJS you can draw shapes on the stage and manipulate them using the following elements: Move Rotate Animate Even if your application has thousands of figures, the animation will run smoothly and with a high enough FPS. The items are organized into layers, of which you can have as many as you want. Shapes can also be organized into groups. KineticJS allows unlimited nesting of shapes and groups. Scenes, layers, groups, and figures are virtual nodes, similar to DOM nodes in HTML. Any node can be styled or transformed. There are several predefined shapes, such as rectangles, circles, images, text, lines, polygons, stars, and so on. You can also create custom drawing functions in order to create custom shapes. For each object you can assign different event handlers (touch or mouse). You can also apply filter or animation to the shapes. Of course, you can implement all the necessary HTML5 Canvas functionality without KineticJS, but you have to spend a lot more time, and not necessarily get the same level of performance. The creators of KineticJS put all their love and faith into a brighter future of HTML5 interactivity. The main advantage of the library is high performance, which is achieved by creating two canvas renderers – a scene renderer and a hit graph renderer. One renderer is what you see, and the second is a special hidden canvas that's used for high-performance event detection. A huge advantage of KineticJS is that it is an extension to HTML5 Canvas, and thus is perfectly suited for developing applications for mobile platforms. High performance can hide all the flaws of the canvas in iOS, Android, and other platforms. It is a known fact that the iOS platform does not support Adobe Flash. In this case, KineticJS is a good Flash alternative for iOS devices. You can wrap up your KineticJS application with Cordova/PhoneGap and use it as an offline application, or publish to the App store. In short, the following are the main advantages of KineticJS: Speed Scalability Extensibility Flexibility Familiarity with API (for developers with the knowledge of HTML, CSS, JS, and jQuery) If you are an active innovator and indomitable web developer, this library is for you. Summary In this article, we walked through the basics and main advantages KineticJS. Resources for Article : Further resources on this subject: HTML5 Presentations - creating our initial presentation [Article] Removing Unnecessary jQuery Loads [Article] Using JavaScript Effects with Joomla! [Article]
Read more
  • 0
  • 0
  • 3915

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-using-storyboards
Packt
14 Jun 2013
7 min read
Save for later

Using Storyboards

Packt
14 Jun 2013
7 min read
(For more resources related to this topic, see here.) Configuring storyboards for a project Getting ready In this recipe, we will learn how to configure an application's project properties using Xcode so that it is set up correctly to use a storyboard file. How to do it... To begin, perform the following simple steps: Select your project from the project navigator window. Then, select your project target from under the TARGETS group and select the Summary tab. Select MainStoryboard from the Main Storyboard drop-down menu, as shown in the preceding screenshot. How it works... In this recipe, we gained an understanding of what storyboards are, as well as how they differ from user interfaces created in the past, whereby a new view would need to be created for each XIB file for your application. Whether you are creating applications for the iPad or iPhone, each view controller that gets created within your storyboard represents the contents of a single screen, comprised of the contents of more than one scene. Each object contained within a view controller can be linked to another view controller that implements another scene. In our final steps, we looked at how to configure our project properties so that it is set up to use the storyboard user interface file by our application. There's more… You can also choose to manually add new Storyboard template to your project. This can be achieved by performing the following simple steps: Select your project from the project navigator window. Select File New | File…| or press command + N. Select the Storyboard template from the list of available templates, located under the User Interface subsection within the iOS section. Click on the Next button to proceed to the next step in the wizard. Ensure that you have selected iPhone from under the Device Family drop-down menu. Click on the Next button to proceed to the next step in the wizard. Specify the name of the storyboard file within the Save As field as the name of the file to be created. Click on the Create button to save the file to the specified folder. Finally, when we create our project using storyboards, we will need to modify our application's delegate AppDelegate.m file, as shown in the following code snippet: - (BOOL)application:(UIApplication *)application didFinishLaunchin gWithOptions:(NSDictionary *)launchOptions { // Override point for customization after // application launch. return YES; } For more information about using storyboards in your applications, you can refer to the Apple Developer documentation, located at https://developer.apple.com/library/ios/#documentation/ToolsLanguages/Conceptual/Xcode4UserGuide/InterfaceBuilder/InterfaceBuilder. Creating a Twitter application In this recipe, we will learn how to create a single view application to build our Twitter application. Getting ready In this recipe, we will start by creating our TwitterExample project. How to do it... To begin with creating a new Xcode project, perform the following simple steps: Launch Xcode from the /Developer/Applications folder. Select Create a new Xcode project, or click on File | New | Project…. Select Single View Application from the list of available templates. Click on the Next button to proceed to the next step in the wizard. Next, enter in TwitterExample as the name of your project. Select iPhone from under the Devices drop-down menu. Ensure that the Use Storyboards checkbox has been checked. Ensure that the Use Automatic Reference Counting checkbox has been checked. Ensure that the Include Unit Tests checkbox has not been checked. Click on the Next button to proceed to the next step in the wizard. Specify the location where you would like to save your project. Then, click on the Create button to save your project at the specified location. The Company Identifier for your app needs to be unique. Apple recommends that you use the reverse domain style (for example, com.domainName.appName). Once your project has been created, you will be presented with the Xcode development environment, along with the project files that the template created for you. How it works... In this recipe, we just created an application that contains a storyboard and consists of one view controller, which does not provide any functionality at the moment. In the following recipes, we will look at how we can add functionality to view controllers, create storyboard scenes, and transition between them. Creating storyboard scenes The process of creating scenes involves adding a new view controller to the storyboard, where each view controller is responsible for managing a single scene. A better way to describe scenes would be to think of a movie reel, where each frame that is being displayed is the actual scene that connects onto the next part. Getting ready When adding scenes to your storyboard file, you can add controls and views to the view controller's view, just as you would do for an XIB file, and have the ability to configure outlets and actions between your view controllers and its views. How to do it... To add a new scene into your storyboard file, perform the following simple steps: From the project navigator, select the file named MainStoryboard.storyboard. From Object Library, select and drag a new View Controller object on to the storyboard canvas. This is shown in the following screenshot: Next, drag a Label control on to the view and change the label's text property to read About Twitter App. Next, drag a Round Rect Button control on to the view that we will use in a later section to call the calling view. In the button's attributes, change the text to read Go Back. Next, on the first view controller, drag a Round Rect Button control on to the view. In the button's attributes, change the text to read About Twitter App. This will be used to call the new view that we added in the previous step. Next, on the first view controller, drag a Round Rect Button control on to the view, underneath the About Twitter App button that we created in the previous step. In the button's attributes, change the text to read Compose Tweet. Next, save your project by selecting File | Save from the menu bar, or alternatively by pressing command + S. Once you have added the controls to each of the view, your final interface should look something like what is shown in the following screenshot: The next step is to create the Action event for our Compose Tweet button so that it has the ability to post tweets. To create an action, perform the following steps: Open the assistant editor by selecting Navigate | Open In Assistant Editor or by pressing option + command + ,. Ensure that the ViewController.h interface file gets displayed. Select the Compose Tweet button; hold down the control key, and drag it from the Compose Tweet button to the ViewController.h interface file between the @interface and @end tags. Choose Action from the Connection drop-down menu for the connection to be created. Enter composeTweet for the name of the method to create. Choose UIButton from the Type drop-down menu for the type of method to create. The highlighted line in the following code snippet shows the completed ViewController.h interface file, with our method that will be responsible for calling and displaying our tweet sheet. // ViewController.h // TwitterExample // // Created by Steven F Daniel on 21/09/12. // Copyright (c) 2012 GenieSoft Studios. All rights reserved. #import @interface ViewController : UIViewController // Create the action methods - (IBAction)composeTweet:(UIButton *)sender; @end Now that we have created our scene, buttons, and actions, our next step is to configure the scene, which is shown in the next recipe. How it works... In this recipe, we looked at how we can add a new view controller to our storyboard and then started to add controls to each of our view controllers and customize their properties. Next, we looked at how we can create an Action event for our Compose Tweet button that will be responsible for responding and executing the associated code behind it to display our tweet sheet. Instead of us hooking up an event handler to the TouchUpInside event of the button, we decided to simply add an action to it and handle the output of this ourselves. These types of actions are called "instance methods". Here we are basically creating the Action method that will be responsible for allowing the user to compose and send a Twitter message.
Read more
  • 0
  • 0
  • 10518
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 €18.99/month. Cancel anytime
article-image-so-what-play
Packt
14 Jun 2013
11 min read
Save for later

So, what is Play?

Packt
14 Jun 2013
11 min read
(For more resources related to this topic, see here.) Quick start – Creating your first Play application Now that we have a working Play installation in place, we will see how easy it is to create and run a new application with just a few keystrokes. Besides walking through the structure of our Play application, we will also look at what we can do with the command-line interface of Play and how fast modifications of our application are made visible. Finally, we will take a look at the setup of integrated development environments ( IDEs ). Step 1 – Creating a new Play application So, let's create our first Play application. In fact, we create two applications, because Play comes with the APIs for Java and Scala, the sample accompanying us in this book is implemented twice, each in one separate language. Please note that it is generally possible to use both languages in one project. Following the DRY principle, we will show code only once if it is the same for the Java and the Scala application. In such cases we will use the play-starter-scala project. First, we create the Java application. Open a command line and change to a directory where you want to place the project contents. Run the play script with the new command followed by the application name (which is used as the directory name for our project): $ play new play-starter-java We are asked to provide two additional information: The application name, for display purposes. Just press the Enter key here to use the same name we passed to the play script. You can change the name later by editing the appName variable in play-starter-java/project/Build.scala. The template we want to use for the application. Here we choose 2 for Java. Repeat these steps for our Scala application, but now choose 1 for the Scala template. Please note the difference in the application name: $ play new play-starter-scala The following screenshot shows the output of the play new command: On our way through the next sections, we will build an ongoing example step-by-step. We will see Java and Scala code side-by-side, so create both projects if you want to find out more about the difference between Java and Scala based Play applications. Structure of a Play application Physically, a Play application consists of a series of folders containing source code, configuration files, and web page resources. The play new command creates the standardized directory structure for these files: /path/to/play-starter-scala└app source code| └controllers http request processors| └views templates for html files└conf configuration files└project sbt project definition└public folder containing static assets| └images images| └javascripts javascript files| └stylesheets css style sheets└test source code of test cases During development, Play generates several other directories, which can be ignored, especially when using a version control system: /path/to/play-starter-scala└dist releases in .zip format└logs log files└project THIS FOLDER IS NEEDED| └project but this...| └target ...and this can be ignored└target generated sources and binaries There are more folders that can be found in a Play application depending on the IDE we use. In particular, a Play project has optional folders on more involved topics we do not discuss in this book. Please refer to the Play documentation for more details. The app/ folder The app/ folder contains the source code of our application. According to the MVC architectural pattern, we have three separate components in the form of the following directories: app/models/: This directory is not generated by default, but it is very likely present in a Play application. It contains the business logic of the application, for example, querying or calculating data. app/views/: In this directory we find the view templates. Play's view templates are basically HTML files with dynamic parts. app/controllers/: This controllers contain the application specific logic, for example, processing HTTP requests and error handling. The default directory (or package) names, models, views, and controllers, can be changed if needed. The conf/ directory The conf/ directory is the place where the application's configuration files are placed. There are two main configuration files: application.conf: This file contains standard configuration parameters routes – This file defines the HTTP interface of the application The application.conf file is the best place to add more configuration options if needed for our application. Configuration files for third-party libraries should also be put in the conf/ directory or an appropriate sub-directory of conf/. The project/ folder Play builds applications with the Simple Build Tool ( SBT ). The project/ folder contains the SBT build definitions: Build.scala: This is the application's build script executed by SBT build.properties: This definition contains properties such as the SBT version plugins.sbt: This definition contains the SBT plugins used by the project The public/ folder Static web resources are placed in the public/ folder. Play offers standard sub-directories for images, CSS stylesheets, and JavaScript files. Use these directories to keep your Play applications consistent. Create additional sub-directories of public/ for third-party libraries for a clear resource management and to avoid file name clashes. The test/ folder Finally, the test/ folder contains unit tests or functional tests. This code is not distributed with a release of our application. Step 2 – Using the Play console Play provides a command-line interface (CLI), the so-called Play console. It is based on the SBT and provides several commands to manage our application's development cycle. Starting our application To enter the Play console, open a shell, change to the root directory of one of our Play projects, and run the play script. $ cd /path/to/play-starter-scala$ play On the Play console, type run to run our application in development (DEV) mode. [play-starter-scala] $ run Use ~run instead of run to enable automatic compilation of file changes. This gives us an additional performance boost when accessing our application during development and it is recommended by the author. All console commands can be called directly on the command line by running play <command>. Multiple arguments have to be denoted in quotation marks, for example, play "~run 9001" A web server is started by Play, which will listen for HTTP requests on localhost:9000 by default. Now open a web browser and go to this location. The page displayed by the web browser is the default implementation of a new Play application. To return to our shell, type the keys Ctrl + D to stop the web server and get back to the Play console. Play console commands Besides run , we typically use the following console commands during development: clean: This command deletes cached files, generated sources, and compiled classes compile: This command compiles the current application test: This command executes unit tests and functional tests We get a list of available commands by typing help play in the Play development console. A release of an application is started with the start command in production (PROD) mode. In contrast to the DEV mode no internal state is displayed in the case of an error. There are also commands of the play script, available only on the command line: clean-all: This command deletes all generated directories, including the logs. debug: This command runs the Play console in debug mode, listening on the JPDA port 9999. Setting the environment variable JDPA_PORT changes the port. stop: This command stops an application that is running in production mode. Closing the console We exit the Play console and get back to the command line with the exit command or by simply typing the key Ctrl + D . Step 3 – Modifying our application We now come to the part that we love the most as impatient developers: the rapid development turnaround cycles. In the following sections, we will make some changes to the given code of our new application visible. Fast turnaround – change your code and hit reload! First we have to ensure that our applications are running. In the root of each of our Java and Scala projects, we start the Play console. We start our Play applications in parallel on two different ports to compare them side-by-side with the commands ~run and ~run 9001. We go to the browser and load both locations, localhost:9000 and I Then we open the default controller app/controllers/Application.java and app/controllers/Application.scala respectively, which we created at application creation, in a text editor of our choice, and change the message to be displayed in the Java code: public class Application extends Controller {public static Result index() {return ok(index.render("Look ma! No restart!"));}} and then in the Scala code: object Application extends Controller {def index = Action {Ok(views.html.index("Look ma! No restart!"))}} Finally, we reload our web pages and immediately see the changes: That's it. We don't have to restart our server or re-deploy our application. The code changes take effect by simply reloading the page. Step 4 – Setting up your preferred IDE Play takes care of automatically compiling modifications we make to our source code. That is why we don't need a full-blown IDE to develop Play applications. We can use a simple text editor instead. However, using an IDE has many advantages, such as code completion, refactoring assistance, and debugging capabilities. Also it is very easy to navigate through the code. Therefore, Play has built-in project generation support for two of the most popular IDEs: IntelliJ IDEA and Eclipse . IntelliJ IDEA The free edition, IntelliJ IDEA Community , can be used to develop Play projects. However, the commercial release, IntelliJ IDEA Ultimate , includes Play 2.0 support for Java and Scala. Currently, it offers the most sophisticated features compared to other IDEs.More information can be found here: http://www.jetbrains.com/idea and also here: http://confluence.jetbrains.com/display/IntelliJIDEA/Play+Framework+2.0 We generate the required IntelliJ IDEA project files by typing the idea command on the Play console or by running it on the command line: $ play idea We can also download the available source JAR files by running idea with-source=true on the console or on the command line: $ play "idea with-source=true" After that, the project can be imported into IntelliJ IDEA. Make sure you have the IDE plugins Scala, SBT , and Play 2 (if available) installed. The project files have to be regenerated by running play idea every time the classpath changes, for example, when adding or changing project dependencies. IntelliJ IDEA will recognize the changes and reloads the project automatically. The generated files should not be checked into a version control system, as they are specific to the current environment. Eclipse Eclipse is also supported by Play. The Eclipse Classic edition is fine, which can be downloaded here: http://www.eclipse.org/downloads. It is recommended to install the Scala IDE plugin, which comes up with great features for Scala developers and can be downloaded here: http://scala-ide.org. You need to download Version 2.1.0 (milestone) or higher to get Scala 2.10 support for Play 2.1. A Play 2 plugin exists also for Eclipse, but it is in a very early stage. It will be available in a future release of the Scala IDE. More information can be found here: https://github.com/scala-ide/scala-ide-play2/wiki The best way to edit Play templates with Eclipse currently is by associating HTML files with the Scala Script Editor. You get this editor by installing the Scala Worksheet plugin, which is bundled with the Scala IDE. We generate the required Eclipse project files by typing the eclipse command on the Play console or by running it on the command line: $ play eclipse Analogous to the previous code, we can also download available source JAR files by running eclipse with-source=true on the console or on the command line: $ play "eclipse with-source=true" Also, don't check in generated project files for a version control system or regenerate project files if dependencies change. Eclipse (Juno) is recognizing the changed project files automatically. Other IDEs Other IDEs are not supported by Play out of the box. There are a couple of plugins, which can be configured manually. For more information on this topic, please consult the Play documentation. Summary We saw how easy it is to create and run a new application with just a few keystrokes. Besides walking through the structure of our Play application, we also looked at what we can do with the command-line interface of Play and how fast modifications of our application are made visible. Finally, we looked at the setup of integrated development environments ( IDEs ). Resources for Article : Further resources on this subject: Play! Framework 2 – Dealing with Content [Article] Play Framework: Data Validation Using Controllers [Article] Play Framework: Binding and Validating Objects and Rendering JSON Output [Article]
Read more
  • 0
  • 0
  • 2304

article-image-ibm-cognos-workspace-advanced
Packt
14 Jun 2013
5 min read
Save for later

IBM Cognos Workspace Advanced

Packt
14 Jun 2013
5 min read
(For more resources related to this topic, see here.) Who should use Cognos Workspace Advanced? With Cognos Workspace Advanced, business users have one tool for creating advanced analyses and reports. The tool, like Query Studio and Analysis Studio, is designed for ease of use and is built on the same platform as the other report development tools in Cognos. Business Insight Advanced/Cognos Workspace Advanced is actually so powerful that it is being positioned more as a light Cognos Report Studio than as a powerful Cognos Query Studio and Cognos Analysis Studio. Comparing to Cognos Query Studio and Cognos Analysis Studio With so many options for business users, how do we know which tool to use? The best approach for making this decision is to consider the similarities and differences between the options available. In order to help us do so, we can use the following table: Feature Query Studio Analysis Studio Cognos Workspace Advanced Ad hoc reporting X   X Ad hoc analysis   X X Basic charting X X X Advanced charting     X Basic filtering X X X Advanced filtering     X Basic calculations X X X Advanced calculations     X Properties pane     X External data     X Freeform design     X As you can see from the table, all three products have basic charting, basic filtering, and basic calculation features. Also, we can see that Cognos Query Studio and Cognos Workspace Advanced both have ad hoc reporting capabilities, while Cognos Analysis Studio and Cognos Workspace Advanced both have ad hoc analysis capabilities. In addition to those shared capabilities, Cognos Workspace Advanced also has advanced charting, filtering, and calculation features. Cognos Workspace Advanced also has a limited properties pane (similar to what you would see in Cognos Report Studio). Furthermore, Cognos Workspace Advanced allows end users to bring in external data from a flat file and merge it with the data from Cognos Connection. Finally, Cognos Workspace Advanced has free-form design capabilities. In other words, you are not limited in where you can add charts or crosstabs in the way that Cognos Query Studio and Cognos Analysis Studio limit you to the standard templates. The simple conclusion after performing this comparison is that you should always use Cognos Workspace Advanced. While that will be true for some users, it is not true for all. With the additional capabilities come additional complexities. For your most basic business users, you may want to keep them using Cognos Query Studio or Cognos Analysis Studio for their ad hoc reporting and ad hoc analysis simply because they are easier tools to understand and use. However, for those business users with basic technical acumen, Cognos Workspace Advanced is clearly the superior option. Accessing Cognos Workspace Advanced I would assume now that, after reviewing the capabilities Cognos Workspace Advanced brings to the table, you are anxious to start using it. We will start off by looking at how to access the product. The first way to access Cognos Workspace Advanced is through the welcome page. On the welcome page, you can get to Cognos Workspace Advanced by clicking on the option Author business reports: This will bring you to a screen where you can select your package. In Cognos Query Studio or Cognos Analysis Studio, you will only be able to select non-dimensional and dimensional packages based on the tool you are using. With Cognos Workspace Advanced, because the tool can use both dimensional and non-dimensional packages, you will be prompted with packages for both. The next way to access Cognos Workspace Advanced is through the Launch menu in Cognos Connection. Within the menu, you can simply choose Cognos Workspace Advanced to be taken to the same options for choosing a package. Note, however, that if you have already navigated into a package, it will automatically launch Cognos Workspace Advanced using the very same package. The third way to access Cognos Workspace Advanced is by far the most functional way. You can actually access Cognos Workspace Advanced from within Cognos Workspace by clicking on the Do More... option on a component of the dashboard: When you select this option, the object will expand out and open for editing inside Cognos Workspace Advanced. Then, once you are done editing, you can simply choose the Done button in the upper right-hand corner to return to Cognos Workspace with your newly updated object. For the sake of showing as many features as possible in this chapter, we will launch Cognos Workspace Advanced from the welcome page or from the Launch menu and select a package that has an OLAP data source. For the purpose of following along, we will be using the Cognos BI sample package great_outdoors_8 (or Great Outdoors). When we first access it, we are prompted to choose a package. For these examples, we will choose great_outdoors_8: We are then brought to a splash screen where we can choose Create new or Open existing. We will choose Create new. We are then prompted to pick the type of chart we want to create. As we will see from the following screenshot, our options are: Blank: It starts us off with a completely blank slate List: It starts us off with a list report Crosstab: It starts us off with a crosstab Chart: It starts us off with a chart and loads the chart wizard Financial: It starts us off with a crosstab formatted like a financial report Existing...: It allows us to open an existing report We will choose Blank because we can still add as many of the other objects as we want to later on.
Read more
  • 0
  • 0
  • 3242

article-image-architecture-freeswitch
Packt
14 Jun 2013
13 min read
Save for later

Architecture of FreeSWITCH

Packt
14 Jun 2013
13 min read
(For more resources related to this topic, see here.) A revolution has begun and secrets have been revealed How and why the telephone works is a mystery to most people. It has been kept secret for years. We just plugged our phones into the wall and they worked, and most people do just that and expect it to work. The telephony revolution has begun, and we have begun to pry its secrets from the clutches of the legacy of the telephony industry. Now, everyday individuals like you and me are able to build phone systems that outperform traditional phone services and offer advanced features for relatively low cost. Some people even use FreeSWITCH to provide telephone services for making a profit. FreeSWITCH has been designed to make all of this easier, so we will go over the architecture to get a better understanding of how it works. Do not be concerned if some of the concepts we introduce seem unnaturally abstract. Learning telephony takes time, especially VoIP. In fact, we recommend that you read this article more than once. Absorb as much as you can on the first pass. You will be surprised at how much your understanding of VoIP and FreeSWITCH has improved.Give yourself plenty of time to digest all of these strange new concepts, and soon you will find that you are a skilled FreeSWITCH administrator. If you keep at it, you will be rewarded with a meaningful understanding of this strange and wonderful world we call telephony. Telephones and telephony systems (such as telephone switches and PBXs) are very complicated and have evolved over the years into several varieties. The most popular type of phone in the U.K. and the U.S. is the traditional analog phone, which we affectionately refer to as POTS lines or Plain Old Telephone Service. From the traditional Ma Bell phone up to the long-range cordless phones that most of us have today, one thing has remained the same—the underlying technology. In the last 10-15 years, there has been a convergence of technology between computers and telephones that has produced a pair of affordable alternatives to POTS lines—Mobile phones and VoIP phones (also called Internet Phones). FreeSWITCH fits into this big tangled mess of various telephone technologies by bridging them together, so that they can communicate despite being otherwise completely incompatible. FreeSWITCH also bridges telephone calls with computer programs that you can write yourself, and controls what happens in ways like never before. FreeSWITCH is software that runs on Windows and several UNIX varieties such as Mac OS X, Linux, Solaris, and BSD. This means you can install FreeSWITCH on your home PC or even a high-end server and use it to process phone calls. The FreeSWITCH design – modular, scalable, and stable The design goal of FreeSWITCH is to provide a modular, scalable system around a stable switching core, and to provide a robust interface for developers to add to and control the system. Various elements in FreeSWITCH are independent of each other and do not have much knowledge about how the other parts are working, other than what is provided in what are called exposed functions. The functionality of FreeSWITCH can also be extended with loadable modules, which tie a particular external technology into the core. FreeSWITCH has many different module types that revolve around the central core, much like satellites orbiting a planet. The list includes: Module type: Purpose: Endpoint Telephone protocols like SIP/H.323 and POTS lines Application Performs a task such as playing audio or setting data Application Programming Interface (API) Exports a function that takes text input and returns text output, which could be used across modules or from an external connection Automated Speech Recognition (ASR) Interfaces with speech recognition systems Chat Bridges and exchanges various chat protocols Codec Translates between audio formats Dialplan Parses the call details and decides where to route the call Directory Connects directory information services, such as LDAP, to a common core lookup API Event handlers Allows external programs to control FreeSWITCH File Provides an interface to extract and play sound from various audio file formats Formats Plays audio files in various formats Languages Programming language interfaces used for call control Loggers Controls logging to the console, system log, or log files Say Strings together audio files in various languages to provide feedback to say things like phone numbers, time of day, spell words, and so on Text-To-Speech (TTS) Interfaces with text-to-speech engines Timers POSIX or Linux kernel timing in applications XML Interfaces Uses XML for Call Detail Records (CDRs), RADIUS, CURL, LDAP, RPC, and/or SCGI The following image shows what the FreeSWITCH architecture looks like and how the modules orbit the core of FreeSWITCH: By combining the functionality of the various module interfaces, FreeSWITCH can be configured to connect IP phones, POTS lines, and IP-based telephone services. It can also translate audio formats and interfaces with a custom menu system, which you can create by yourself. You can even control a running FreeSWITCH server from another machine. Let's start by taking a closer look at a pair of important module types. Important modules – Endpoint and Dialplan Endpoint modules are critically important and add some of the key features that make FreeSWITCH the powerful platform it is today. The primary role of these modules is to take certain common communication technologies and normalize them into a common abstract entity which we refer to as a session. A session represents a connection between FreeSWITCH and a particular protocol. There are several Endpoint modules that come with FreeSWITCH, which implement several protocols such as SIP, H.323, Jingle (Google Talk), and some others. We will spend some time examining one of the more popular modules named mod_sofia. Sofia-SIP (http://sofia-sip.sourceforge.net) is an open source project sponsored by Nokia, which provides a programming interface for the Session Initiation Protocol (SIP). We use this library in FreeSWITCH in a module we call mod_sofia. This module registers to all the hooks in FreeSWITCH necessary to make an Endpoint module, and translates the native FreeSWITCH constructs into SIP constructs and back again. Configuration information is taken from the central FreeSWITCH configuration files, which allows mod_sofia to load user-defined preferences and connection details. This allows FreeSWITCH to accept registration from SIP phones and devices, register to other SIP Endpoints such as service providers, send notifications, and provide services to the phones such as voicemail. The SIP protocol is defined by a number of RFC (request for comment) documents. The primary RFC can be found at http://www.ietf.org/rfc/rfc3261.txt When a SIP call is established between FreeSWITCH and another SIP device, it will show up in FreeSWITCH as an active session. If the call is inbound, it can be transferred or bridged to interactive voice response (IVR) menus, hold music, or one or more extensions, though numerous other options are available. Let's examine a typical scenario where an SIP phone registered as extension 2000 dials extension 2001 with the hope of establishing a call. First, the SIP phone sends a call setup message to mod_sofia over the network (mod_sofia is listening for such messages). After receiving the message, mod_sofia in turn parses the relevant details and passes the call into the core state machine in FreeSWITCH. The state machine (in the FreeSWITCH core) then sends the call into the ROUTING state. The next step is to locate the Dialplan module based on the configuration data for the calling Endpoint. The default and most widely used Dialplan module is the XML Dialplan module. This module is designed to look up a list of instructions from the central XML registry within FreeSWITCH. The XML Dialplan module will parse a series of XML extension objects using regular expression pattern-matching. As we are trying to call 2001, we hope to find an XML extension testing the destination_number field for something that matches 2001 and routes accordingly. The Dialplan is not limited to matching only a single extension. The XML Dialplan module builds a sort of task list for the call. Each extension that matches it will have its actions added to the call's task list. Assuming FreeSWITCH finds at least one extension, the XML Dialplan will insert instructions into the session object with the information it needs to try and connect the call to 2001. Once these instructions are in place, the state of the calling session changes from ROUTING to EXECUTE, where the next handler drills down the list and executes the instructions obtained during the ROUTING state. This is where the application interface comes into the picture. Each instruction is added to the session in the form of an application name and a data argument that will be passed to that application. The one we will use in this example is the bridge application. The purpose of this application is to create another session with an outbound connection, then connect the two sessions for direct audio exchange. The argument we will supply to bridge will be user/2001, which is the easiest way to generate a call to extension 2001. A Dialplan entry for 2001 might look like this: <extension name="example"><condition field="destination_number"expression="^2001$"><action application="bridge" data="user/2001"/></condition></extension> The extension is named example, and it has a single condition to match. If the condition is matched, it has a single application to execute. In plain language, the mentioned extension could be expressed like this: If the caller dialed 2001, this establishes a connection between the calling party and the endpoint (that is, telephone) at 2001. Consider how this happens. Once we have inserted the instructions into the session, the session's state will change to EXECUTE, and the FreeSWITCH core will use the data collected to perform the desired action. First, the default execute state handler will parse the command to execute bridge on user/2001, then it will look up the bridge application and pass the user/2001 data in. This will cause the FreeSWITCH core to create a new outbound session of the desired type. User 2001 is also a SIP phone, so user/2001 will resolve into a SIP dial string, which will be passed to mod_sofia to ask it to create a new outbound session. If the setup for that new session is successful, there will now be two sessions in the FreeSWITCH core. The bridge application will take the new session and the original session (the caller's phone) and call the bridge function on it. This allows the audio to flow in both directions once the person at extension 2001 actually answers the phone. If that user was unable to answer or was busy, a timeout (that is, a failure) would occur and send the corresponding message back to the caller's phone. If a call is unanswered or an extension is busy, many routing options are possible, including call forwarding or voicemail. All of this happens from the simple action of picking up the phone handset and dialing 2 0 0 1. FreeSWITCH takes all of the complexity of SIP and reduces it to a common denominator. From there, it reduces the complexity further by allowing us to configure a single instruction in the Dialplan to connect the phone at 2000 to the phone at 2001. If we want to allow the phone at 2001 to be able to call the phone at 2000, we can add another entry in the Dialplan going the other way: <extension name="example 2"><condition field="destination_number" expression="^2000$"><action application="bridge" data="user/2000"/></condition></extension> In this scenario, the Endpoint module turned SIP into a FreeSWITCH session and the Dialplan module turned XML into an extension. The bridge application turned the complex code of creating an outbound call and connecting the audio into a simple application/data pair. Both the Dialplan module and the application module interface are designed around regular FreeSWITCH sessions. Therefore, not only does the abstraction make life easier for us at the user level, it also simplifies the design of the application and the Dialplan because they can be made agnostic of the actual endpoint technology involved in the call. It is because of this abstraction, when we make up a new Endpoint module tomorrow for something like Skype (there is actually such a thing present, by the way), that we can reuse all the same application and Dialplan modules. The same principle applies to the Say, Automatic Speech Recognition (ASR), Text-to-Speech (TTS), and other such modules. It is possible that you may want to work with some specific data provided by the Endpoint's native protocol. In SIP, for instance, there are several arbitrary headers as well as several other bits of interesting data from the SIP packets. We solve this problem by adding variables to the channel. Using channel variables, mod_sofia can set these arbitrary values as they are encountered in the SIP data where you can retrieve them by name from the channel in your Dialplan or application. This way, we share our knowledge of these special variables with the SIP Endpoint. However, the FreeSWITCH core just sees them as arbitrary channel variables that the core can ignore. There are also several special reserved channel variables that can influence the behavior of FreeSWITCH in many interesting ways. If you have ever used a scripting language or configuration engine that uses variables (sometimes called attribute-value pairs or AVPs), you are at an advantage because channel variables are pretty much the same concept. There is simply a variable name and a value that is passed to the channel and the data is set. There is even an application interface for this, the set application, which lets you set your own variables from the Dialplan: <extension name="example 3"><condition field="destination_number" expression="^2000$"><action application="set" data="foo=bar"/><action application="bridge" data="user/2000"/></condition></extension> This example is almost identical to the previous example, but instead of just placing the call, we first set the variable foo equal to the value bar. This variable will remain set throughout the call and can even be referenced at the end of the call in the detail logs. The more we build things in small pieces, the more the same underlying resources can be reused, making the system simpler to use. For example, the codec interface knows nothing else about the core, other than its own isolated world of encoding and decoding audio packets. Once a proper codec module has been written, it becomes usable by any Endpoint interface capable of carrying that codec in its audio stream. This means that if we get a Text-To-Speech module working, we can generate synthesized speech on any and all Endpoints that FreeSWITCH supports. It does not matter which one comes first as they have nothing to do with each other. However, the addition of either one instantly adds functionality to the other. The TTS module becomes more useful because it can use more codecs; the codecs have become more useful because we added a new function that can take advantage of them. The same idea applies to applications. If we write a new application module, the existing endpoints will immediately be able to run and use that application.
Read more
  • 0
  • 0
  • 18983

article-image-creating-your-own-theme
Packt
13 Jun 2013
5 min read
Save for later

Creating Your Own Theme

Packt
13 Jun 2013
5 min read
(For more resources related to this topic, see here.) Starting with a new layout Before we start creating a concrete5 theme we need a layout. In this article, we're going to use a simple layout without any pictures to keep the code as short as possible—it's about concrete5, not about HTML and CSS. If you don't have the time for an exercise, you can use your own layout. With good knowledge about the basic technologies of concrete5, you should be able to amend the instructions in this article to match your own layout. If you don't feel very comfortable working with PHP you should probably use the printed HTML code in this article. Here's a screenshot of what our site is going to look like once we've finished our theme: While this layout isn't very pretty, it has an easy structure; navigation on top and a big content area where we can insert any kind of block we want. In case you're using your own layout, try to use one with a simple structure; navigation on top or on the left with one big place for the content, and try to avoid Flash. The HTML code Let's have a look at the HTML code: <!DOCTYPE html><html lang="en"><head><title>concrete5 Theme</title><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><style type="text/css" media="screen">@import "main.css";</style></head><body><div id="wrapper"><div id="page"><div id="header_line_top"></div><div id="header"><ul class="nav-dropdown"><li><a href="#">Home</a></li><li><a href="#">Test</a></li><li><a href="#">About</a></li></ul></div><div id="header_line_bottom"></div><div id="content"><p>Paragraph 1</p><p>Paragraph 2</p><p>Paragraph 3</p></div><div id="footer_line_top"></div><div id="footer"></div><div id="footer_line_bottom"></div></div></div></body></html> There are three highlighted lines in the preceding code: The CSS import: This is to keep the layout instructions separated from the HTML elements; we've got all the CSS rules in a different file named main.css. This is also how almost all concrete5 themes are built. The header block contains the navigation. As we're going to apply some styles to it, make sure it has its own ID. Using an ID also improves the performance when using CSS and JavaScript to access an element, as an ID is unique. The same applies to the content block. Make sure it has a unique ID. Most web technologies we use nowadays are standardized in one way or another. Currently, the most important organization is W3C. They also offer tools to validate your code. Checking your code is never a bad idea. Navigate to http://validator.w3.org/ and enter the address of the website you want to check or in this case, as your website isn't accessible by the public, click on Validate by Direct Input and paste the HTML code to see if there are any mistakes. While it should be fairly easy to produce valid HTML code, things are a bit tricky with CSS. Due to some old browser bugs, you're often forced to use invalid CSS rules. There's often a way to rebuild the layout to avoid some invalid rules but often this isn't the case—you won't be doomed if something isn't 100 percent valid but you're on the safer side if it is. CSS rules As mentioned earlier, all CSS rules are placed in a file named main.css. Let's have a look at all CSS rules you have to put in our CSS file: /* global HTML tag rules */html, body, div, pre, form, fieldset, input, h1, h2, h3, h4, h5, h6,p, textarea, ul, ol, li, dl, dt, dd, blockquote, th, td {margin: 0;padding: 0;}p {margin: 5px 0px 15px 0px;}html {height: 100%;}body {background-color: #989898;height: 100%;}/* layout rules */#wrapper {margin: 0 auto;width: 980px;text-align: left;padding-top: 35px;}#page {background: #FFFFFF;float: left;width: 960px;padding: 5px;-moz-box-shadow: 0 0 15px black;-webkit-box-shadow: 0 0 15px black;box-shadow: 0 0 15pxblack;border-radius: 10px;}/* header */#header {background: #262626;border-radius: 10px 10px 0px 0px;height: 75px;}#header_line_top {background: #262626;height: 0px;}#header_line_bottom {background: #e64116;height: 3px;}/* content */#content {min-height: 300px;padding: 30px;color: #1E1E1E;font-family: verdana, helvetica, arial;font-size: 13px;line-height: 22px;}/* footer */#footer {background: #262626;height: 75px;border-radius: 0px 0px 10px 10px;}#footer_line_top {background: #e64116;height: 3px;}#footer_line_bottom {background: #262626;height: 0px;}/* header navigation */#header ul{margin: 0px;padding: 20px;}#header ul li {float: left;list-style-type: none;}#header ul li a {margin-right: 20px;display: block;padding: 6px 15px 6px 15px;color: #ccc;text-decoration: none;font-family: verdana, helvetica, arial;}#header ul li a:hover {color: white;}
Read more
  • 0
  • 0
  • 2015
article-image-customize-your-linkedin-profile-headline
Packt
13 Jun 2013
2 min read
Save for later

Customize your LinkedIn profile headline

Packt
13 Jun 2013
2 min read
(For more resources related to this topic, see here.) Every LinkedIn user can customize his/her profile headline. Your headline is the first thing that is read about you by other LinkedIn users, even before they get a chance to have a look at your detailed profile. Hence, this tool should be used wisely so that it can attract the right audience. The following screenshot shows what a profile headline looks like: How to do it... To set up your LinkedIn profile headline, perform the following steps: Click on the Edit Profile button from the LinkedIn toolbar located at the top of the page that appears after you log in. Click on the button located next to your current headline, and you will see a screen, as shown in the following screenshot: Input the professional headline for the target audience. How it works... You've now learned how to update your LinkedIn profile headline. The key point is to be as specific as you can and put the right keywords that are search engine friendly and eye catching. Let me state a few examples: Job seeker headline: 5 years of exp in Java and .NET; looking for opportunities in Hong Kong Service marketing headline: Helping fortune 500 companies increase revenues by designing better HR strategies Examples of a few other interesting headlines: Chief Operating Officer; building high performing sales teams that align with corporate vision Experienced sales professional looking to positively impact a new organization Retail technology solutions; developing high performing retail outlets Summary It is a good idea to refine and update your profile headline regularly, so that your profile is viewed by the right audience. Thus, we have learnt how to customize the LinkedIn profile headline. Resources for Article : Further resources on this subject: Managing the Discussion Forums Using PHP-Nuke [Article] Safely Manage Different Versions of Content with Plone [Article] Customizing Headers and Footers with MS Office Live Small Business [Article]
Read more
  • 0
  • 0
  • 13805

Packt
12 Jun 2013
8 min read
Save for later

A quick start – OpenCV fundamentals

Packt
12 Jun 2013
8 min read
(For more resources related to this topic, see here.) The OpenCV library has a modular structure, and the following diagram depicts the different modules available in it: A brief description of all the modules is as follows: Module Feature Core A compact module defining basic data structures, including the dense multidimensional array Mat and basic functions used by all other modules. Imgproc An image processing module that includes linear and non-linear image filtering, geometrical image transformations (resize, affine and perspective warping, generic table-based remapping), color space conversion, histograms, and so on. Video A video analysis module that includes motion estimation, background subtraction, and object tracking algorithms. Calib3d Basic multiple-view geometry algorithms, single and stereo camera calibration, object pose estimation, stereo correspondence algorithms, and elements of 3D reconstruction. Features2d Salient feature detectors, descriptors, and descriptor matchers. Objdetect Detection of objects and instances of the predefined classes; for example, faces, eyes, mugs, people, cars, and so on. Highgui An easy-to-use interface to video capturing, image and video codecs, as well as simple UI capabilities. Gpu GPU-accelerated algorithms from different OpenCV modules. Task 1 – image basics When trying to recreate the physical world around us in digital format via a camera, for example, the computer just sees the image in the form of a code that just contains the numbers 1 and 0. A digital image is nothing but a collection of pixels (picture elements) which are then stored in matrices in OpenCV for further manipulation. In the matrices, each element contains information about a particular pixel in the image. The pixel value decides how bright or what color that pixel should be. Based on this, we can classify images as: Greyscale Color/RGB Greyscale Here the pixel value can range from 0 to 255 and hence we can see the various shades of gray as shown in the following diagram. Here, 0 represents black and 255 represents white: A special case of grayscale is the binary image or black and white image. Here every pixel is either black or white, as shown in the following diagram: Color/RGB Red, Blue, and Green are the primary colors and upon mixing them in various different proportions, we can get new colors. A pixel in a color image has three separate channels— one each for Red, Blue, and Green. The value ranges from 0 to 255 for each channel, as shown in the following diagram: Task 2 – reading and displaying an image We are now going to write a very simple and basic program using the OpenCV library to read and display an image. This will help you understand the basics. Code A simple program to read and display an image is as follows: // opencv header files #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/core.hpp" // namespaces declaration using namespace cv; using namespace std; // create a variable to store the image Mat image; int main( int argc, char** argv ) { // open the image and store it in the 'image' variable // Replace the path with where you have downloaded the image image=imread("<path to image">/lena.jpg"); // create a window to display the image namedWindow( "Display window", CV_WINDOW_AUTOSIZE ); // display the image in the window created imshow( "Display window", image ); // wait for a keystroke waitKey(0); return 0; } Code explanation Now let us understand how the code works. Short comments have also been included in the code itself to increase the readability. #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/core.hpp" The preceding two header files will be a part of almost every program we write using the OpenCV library. As explained earlier, the highgui header is used for window creation, management, and so on, while the core header is used to access the Mat data structure in OpenCV. using namespace cv; using namespace std; The preceding two lines declare the required namespaces for this code so that we don't have to use the :: (scope resolution) operator every time for accessing the functions. Mat image; With the above command, we have just created a variable image of the datatype Mat that is frequently used in OpenCV to store images. image=imread("<path to image">/lena.jpg"); In the previous command, we opened the image lena.jpg and stored it in the image variable. Replace <path to image> in the preceding command with the location of that picture on your PC. namedWindow( "Display window", CV_WINDOW_AUTOSIZE ); We now need a window to display our image. So, we use the above function to do the same. This function takes two parameters, out of which the first one is the name of the window. In our case, we would like to name our window Display Window. The second parameter is optional, but it resizes the window based on the size of the image so that the image is not cropped. imshow( "Display window", image ); Finally, we are ready to display our image in the window we just created by using the preceding function. This function takes two parameters out of which the first one is the window name in which the image has to be displayed. In our case, obviously, that will be Display Window . The second parameter is the image variable containing the image that we want to display. In our case, it's the image variable. waitKey(0); Last but not least, it is advised that you use the preceding function in most of the codes that you write using the OpenCV library. If we don't write this code, the image will be displayed for a fraction of a second and the program will be immediately terminated. It happens so fast that you will not be able to see the image. What this function does essentially is that it waits for a keystroke from the user and hence it delays the termination of the program. The delay here is in milliseconds. Output The image can be displayed as follows: Task 3 – resizing and saving an image We are now going to write a very simple and basic program using the OpenCV library to resize and save an image. Code The following code helps you to resize a given image: // opencv header files #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/core/core.hpp" // namespaces declaration using namespace std; using namespace cv; int main(int argc, char** argv) { // create variables to store the images Mat org, resized,saved; // open the image and store it in the 'org' variable // Replace the path with where you have downloaded the image org=imread("<path to image>/lena.png"); //Create a window to display the image namedWindow("Original Image",CV_WINDOW_AUTOSIZE); //display the image imshow("Original Image",org); //resize the image resize(org,resized,Size(),0.5,0.5,INTER_LINEAR); namedWindow("Resized Image",CV_WINDOW_AUTOSIZE); imshow("Resized Image",resized); //save the image //Replace <path> with your desired location imwrite("<path>/saved.png",resized; namedWindow("Image saved",CV_WINDOW_AUTOSIZE); saved=imread("<path to image>/saved.png"); imshow("Image saved",saved); //wait for a keystroke waitKey(0); return 0; } Code explanation Only the new functions/concepts will be explained in this case. #include "opencv2/imgproc/imgproc.hpp" Imgproc is another useful header that gives us access to the various transformations, color conversions, filters, histograms, and so on. Mat org, resized; We have now created two variables, org and resized, to store the original and resized images respectively. resize(org,resized,Size(),0.5,0.5,INTER_LINEAR); We have used the preceding function to resize the image. The preceding function takes six parameters, out of which the first one is the variable containing the source image to be modified. The second one is the variable to store the resized image. The third parameter is the output image size. In this case we have not specified this, but we have instead used the Size() function, which will automatically calculate it based on the values of the fourth and fifth parameters. The fourth and fifth parameters are the scale factors along the horizontal and vertical axes respectively. The sixth parameter is for choosing the type of interpolation method. We have used the bilinear interpolation, which is the default method. imwrite("<path>/saved.png",final); Finally, using the preceding function, you can save an image to a particular location on our PC. The function takes two parameters, out of which the first one is the location where you want to store the image and the second is the variable in which the image is stored. This function is very useful when you want to perform multiple operations on an image and save the image on your PC for future reference. Replace <path> in the preceding function with your desired location. Output Resizing can be demonstrated through the following output: Summary This section showed you how to perform a few of the basic tasks in OpenCV as well as how to write your first OpenCV program. Resources for Article : Further resources on this subject: OpenCV: Segmenting Images [Article] Tracking Faces with Haar Cascades [Article] OpenCV: Image Processing using Morphological Filters [Article]
Read more
  • 0
  • 0
  • 8544

article-image-top-features-youll-want-know-about
Packt
12 Jun 2013
10 min read
Save for later

Top features you'll want to know about

Packt
12 Jun 2013
10 min read
(For more resources related to this topic, see here.) 1 – Track changes and production revisions (for Adobe Story Plus only) It is important to keep track of any changes you or someone else may make to a document. It's easy to save over the previous version with the new one, but what if you want to compare the previous and current versions to one another? You are able to track any and all revisions through this feature. Called revision styles, all revisions become associated with a unique style for easier identification. Track changes Before moving to revisions, we need to be able to know how to insert and track changes made to a document. This is how it is done: When in the AUTHORING view, in the document, go to the Review tab in the top tool bar. Check Start Tracking Changes to enable it, and uncheck it to disable: When it is checked, any new content you add will be in red text and highlighted: There is a speech bubble on the right-hand side of the addition, which allows for the person making the change to add a comment. Click on the icon to open the comment window: When you place the cursor over the inserted change, a new bubble will appear telling you who made the change and when. On the far right-hand side, you can either accept or reject the change: Production revisions You have to be in the Authoring view in order to make a revision. Production revisions highlight certain pages where changes have been made. The script becomes locked and all changes are highlighted in the revision style you choose. On the title page, a note is inserted on the bottomright corner giving the date of the last revision. This is also done on the footer of every page where there is a change. The color changes and borders will not be exported in a PDF. Before starting a revision, make sure that you have done the following: Act on all tracked changes in your document by accepting or rejecting them. Disable track changes after completing accepting/rejecting tracked changes. Now, after completing the preceding steps, follow these steps: Select Production | Start Revision. In the Active Revision drop-down, choose a revision style: This style will be used for the markups in the revision. Make sure that you haven't already used the chosen style for a previous revision document. Click Start Revision. Creating a revision style Follow these steps to create your revision style: Select Production | Manage Revisions. Click on the + icon. Enter a name for the style The following options can be tailored according to your needs: Revision Color: Used to choose a color from the color menu. This color will then be applied to all the revised text and the border of the individual pages that contain the revisions. The border color will not be displayed in a printed or exported document. Mark: The default mark is displayed on the right of the revised content. You can change this mark by choosing any symbol of your liking. Date: The revision date. Revision Text Style: The chosen formatting option is used to display revised text. Click Done and your new style will be available from now on. Deleting or modifying existing revisions Let's take a look at how we can delete or modify already existing revisions: Select the style that you want to delete or modify. You can do either of the following: Click on the - sign to delete the style To modify, simply edit its values and click Done Display options for revisions Adobe Story also provides some display options for revisions, here's how we can set them up: Select Production | Manage Revisions. In Viewing Options, the following display options can be personalized according to your needs: Show Markup For: The options are Select All or Active. This will let you choose whether you want to have all the markups shown for all revisions or just the active ones. Mark Position: The mark you set in Revision Style is set to the right-hand side by default; you can also change its position. Show Date In Script Header and Footer: If you do not want to display the date, disable this option. Locking or unlocking scene numbers When you lock scene numbers, you prevent the renumbering of existing scenes whenever a new scene is added during production revisions. When you do insert a new scene, Adobe Story will apply a number to the scene preceding it. For example, if you add a new scene in between scene 4 and 5, it will be numbered 4A. Here's how we can lock and unlock scene numbers: Select Production | Manage Scene Numbers. Select the Keep Existing Scene Number option to lock all current scenes. To unlock, deselect Keep Existing Scene Number. Omitting or unomitting scenes Adobe Story allows you to remove a scene without affecting the scene numbers remaining in the script. The word OMITTED will appear at the location of the scene you've chosen to omit. You can, at a later date, unomit the scene if you chose and recover the content. To omit a scene, simply place your cursor on the scene and then select Production | Omit Scene. To unomit a scene, place your cursor on the omitted scene and then select Production | Unomit Scene. Printing production revisions If you want to print your revisions, it is easy to do so; just follow these steps: Select File | Print. Choose any one of the following option: Entire Script All ChangedPages Revision To print in color, select the Print Revised Text In Color option. Identifying the total number of revised pages Here's how we can identify the total number of revised pages: Select Production | Manage Revisions. In Viewing Options, select All and click Done. 2 – Tagging Along with the advent of the "cloud" concept, tagging individual words to content has become something of a norm in today's online society. Adobe Story has incorporated a similar system. With tagging, you can tag words and phrases in your scripts automatically, or manually by using the Tagging Panel option. For example, "boom" can be tagged as "sound effect". Tagging panel To open the panel, you must be first in the AUTHORING view. Select View | Tagging Panel. The panel will open on the right-hand side of the document. To add tags to the panel, enter the name of the tag in the field next to the Create button: To delete a tag from the tagging panel, select the tag and then click on the Delete this Tag link: Tagging automatically You must be in the online mode for the Autotagging feature to work. It will not work in the offline mode. The Autotagging feature is only available for English scripts. This is how it's done: Select File | Tagging | Start Autotagging. Or select it from the drop-down menu option in the Tagging panel: Once you enable Autotagging, the script will be locked. You will have to wait until the process has completed before being able to edit the document; the following screenshot shows the message being displayed: Tagging manually Select View | Tagging Panel. Choose the word or phrase you would like to tag. If what you're choosing has already been tagged, it will be appended to the tag list for the word or phrase. Select a tag from Taglist in the Tagging panel. Do either of the following: Select the Show In Bold option if you want the tagged words or phrases to be displayed in bold. Select the Show Color option if you would prefer Story to display the selected color (you can choose a color for each tag with a color palette on the righthand of the tag in the Taglist panel) to the tag: Finding words or phrases by their specific tag Follow these steps to search for words or phrases with a specific tag: Disable visibility for all tags. Enable visibility for the tag that you want to search. To do this, simply click on the eye icon on the left-hand side of the tagged word: Use the arrow icons in the Tagging panel in order to navigate through the tags in the script. Only the visible tags will be shown. Viewing tags associated with a word or phrase To view tags associated with a word or a phrase, you can do either of the following: Select the word/phrase. The tags associated with the word/phrase will be highlighted in the Tagging panel. Scroll through the panel in order to view the tags associated with it: Move your mouse over the word/phrase. The information will be displayed in the tool tip: Hold Ctrl (Cmd on Mac) and double-click to view the associated tags: Removing tags Over the word you wish to edit, hold Ctrl (Cmd on Mac) and double-click to bring up the Applied Tags panel. Click on the Remove This Tag icon for the chosen tag. Click Close. To remove all the tags, select File | Tagging | Remove All Tags. To remove all the manual tags, select File | Tagging | Remove All Manual Tags. To remove all the auto tags, select File | Tagging | Remove Auto Tags. 3 – Application for iOS-based devices Adobe Story has an application for iOS-based devices. This application is available currently only in English. It allows you to read and review Adobe Story scripts and documents. It does not support AV (Audio Visual) scripts, Multicolumn scripts, and TV scripts as of yet. Logging in Before you start, make sure you have registered yourself with Adobe Story using the web or desktop application. Use the same combination of e-mail address and password used on the full application with the iOS version. Accept the TOU before attempting to log in. If you want to log out, select Account and then select Log Out. Viewing documents, scene outline, and scenes The ten most recently read files will be displayed upon logging in to the Adobe Story application. To view all the documents, click Categories. To view the scene outline, select the script in the Recent Files or Categories view. To view the contents of a scene, select the scene in the scene outline. Use the arrow icons to move among the scenes. To view Notifications, in the Recent Files view, select Notifications. A list of notifications is displayed. Highlighted notifications are for new ones. Reviewing scripts As long as you have author, co-author, or reviewer permissions, you will be able to review a script. Open the script and navigate to the scene. Do one of the following: Double-click to select the content that you want to comment on. Click on Comment, or on the Add Comment button. To comment on the content that has already been commented on, enter your comment in the Write New Comment textbox. To navigate comments, use the arrow icons. Click Post. Viewing or deleting comments In the scene containing the comments, select Comments. The comment list is displayed. The paragraph containing the comment is highlighted when you select on a comment in the list. Select Delete after clicking on the desired comment. Summary In this article we learned about three of Adobe Story's key features. We learned about track changes and production revisions. we learned about tagging, and learned about more about Adobe Story in iOS devices. There is a whole lot more to learn as far as the features in Adobe Story is concerned. Resources for Article : Further resources on this subject: Integrating Scala, Groovy, and Flex Development with Apache Maven [Article] Exporting SAP BusinessObjects Dashboards into Different Environments [Article] An Introduction to Flash Builder 4-Network Monitor [Article]
Read more
  • 0
  • 0
  • 2245
article-image-magento-fundamentals-developers
Packt
11 Jun 2013
13 min read
Save for later

Magento Fundamentals for Developers

Packt
11 Jun 2013
13 min read
(For more resources related to this topic, see here.) Zend Framework – the base of Magento As you probably know, Magento is the most powerful e-commerce platform in the market; what you might not know about Magento is that it is also an object-oriented (OO) PHP framework developed on top of Zend Framework. Zend's official site describes the framework as: Zend Framework 2 is an open source framework for developing web applications and services using PHP 5.3+. Zend Framework 2 uses 100% object-oriented code and utilises most of the new features of PHP 5.3, namely namespaces, late static binding, lambda functions and closures. The component structure of Zend Framework 2 is unique; each component is designed with few dependencies on other components. ZF2 follows the SOLID object oriented design principle. This loosely coupled architecture allows developers to use whichever components they want. We call this a "use-at-will" design. But what is Zend Framework exactly? Zend Framework is an OO framework developed on PHP that implements the Model-View-Controller (MVC) paradigm. When Varien, now Magento Inc., started developing Magento it decided to do it on top of Zend because of the following components: Zend_Cache Zend_Acl Zend_DB Zend_Pdf Zend_Currency Zend_Date Zend_Soap Zend_Http In total, Magento uses around 15 different Zend components. The Varien library directly extends several of the Zend components mentioned previously, for example Varien_Cache_Core extends from Zend_Cache_Core. Using Zend Framework, Magento was built with the following principles in mind: Maintainability: It occurs using code pools to keep the core code separate from local customizations and third-party modules Upgradability: Magento modularity allows extensions and third-party modules to be updated independently from the rest of the system Flexibility: Allows seamless customization and simplifies the development of new features Although having used Zend Framework or even understanding it are not the requirements for developing with Magento, having at least a basic understanding of the Zend components, usage, and interaction can be invaluable information when we start digging deeper into the core of Magento. You can learn more about Zend Framework at http://framework.zend.com/ Magento folder structure Magento folder structure is slightly different from other MVC applications; let's take a look at the directory tree, and each directory and its functions: app: This folder is the core of Magento and is subdivided into three importing directories: code: This contains all our application code divided into three code pools such as core, community, and local design: This contains all the templates and layouts for our application locale: This contains all the translation and e-mail template files used for the store js: This contains all the JavaScript libraries that are used in Magento media: This contains all the images and media files for our products and CMS pages as well as the product image cache lib: This contains all the third-party libraries used in Magento such as Zend and PEAR, as well as the custom libraries developed by Magento, which reside under the Varien and Mage directories skin: This contains all CSS code, images, and JavaScript files used by the corresponding theme var: This contains our temporary data such as cache files, index lock files, sessions, import/export files, and in the case of the Enterprise edition the full page cache folders Magento is a modular system. This means that the application, including the core, is divided into smaller modules. For this reason, the folder structure plays a key role in the organization of each module core; a typical Magento module folder structure would look something like the following figure: Let's review each folder in more detail: Block: This folder contains blocks in Magento that form an additional layer of logic between the controllers and views controllers: controllers folders are formed by actions that process web server requests Controller: The classes in this folder are meant to be abstract classes and extended by the controller class under the the controllers folder etc: Here we can find the module-specific configuration in the form of XML files such as config.xml and system.xml Helper: This folder contains auxiliary classes that encapsulate a common-module functionality and make it available to a class of the same module and to other modules' classes as well Model: This folder contains models that support the controllers in the module for interacting with data sql: This folder contains the installation and upgrade files for each specific module As we will see later on in this article, Magento makes heavy use of factory names and factory methods. This is why the folder structure is so important. Modular architecture Rather than being a large application, Magento is built by smaller modules, each adding specific functionality to Magento. One of the advantages of this approach is the ability to enable and disable specific module functionality with ease, as well as add new functionality by adding new modules. Autoloader Magento is a huge framework, composed of close to 30,000 files. Requiring every single file when the application starts would make it incredibly slow and heavy. For this reason, Magento makes use of an autoloader class to find the required files each time a factory method is called. So, what exactly is an autoloader? PHP5 includes a function called __autoload().When instantiating a class, the __autoload() function is automatically called; inside this function, custom logic is defined to parse the class name and the required file. Let's take a closer look at the Magento bootstrap code located at app/Mage.php: …Mage::register('original_include_path', get_include_path());if (defined('COMPILER_INCLUDE_PATH')) {$appPath = COMPILER_INCLUDE_PATH;set_include_path($appPath . PS .Mage::registry('original_include_path'));include_once "Mage_Core_functions.php";include_once "Varien_Autoload.php";} else {/*** Set include path*/$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';$paths[] = BP . DS . 'lib';$appPath = implode(PS, $paths);set_include_path($appPath . PS .Mage::registry('original_include_path'));include_once "Mage/Core/functions.php";include_once "Varien/Autoload.php";}Varien_Autoload::register(); The bootstrap file takes care of defining the include paths and initializing the Varien autoloader, which will in turn define its own autoload function as the default function to call. Let's take a look under the hood and see what the Varien autoload function is doing: /*** Load class source code** @param string $class*/public function autoload($class){if ($this->_collectClasses) {$this->_arrLoadedClasses[self::$_scope][] = $class;}if ($this->_isIncludePathDefined) {$classFile = COMPILER_INCLUDE_PATH .DIRECTORY_SEPARATOR . $class;} else {$classFile = str_replace(' ', DIRECTORY_SEPARATOR,ucwords(str_replace('_', ' ', $class)));}$classFile.= '.php';//echo $classFile;die();return include $classFile;} The autoload class takes a single parameter called $class, which is an alias provided by the factory method. This alias is processed to generate a matching class name that is then included. As we mentioned before, Magento's directory structure is important due to the fact that Magento derives its class names from the directory structure. This convention is the core principle behind factory methods that we will be reviewing later on in this article. Code pools As we mentioned before, inside our app/code folder we have our application code divided into three different directories known as code pools. They are as follows: core: This is where the Magento core modules that provide the base functionality reside. The golden rule among Magento developers is that you should never, by any circumstance, modify any files under the core code pool. community: This is the location where third-party modules are placed. They are either provided by third parties or installed through Magento Connect. local: This is where all the modules and code developed specifically for this instance of Magento reside. The code pools identify where the module came from and on which order they should be loaded. If we take another look at the Mage.php bootstrap file, we can see the order on which code pools are loaded: $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';$paths[] = BP . DS . 'lib'; This means that for each class request, Magento will look in local, then community, then core, and finally inside the lib folder. This also leads to an interesting behavior that can easily be used for overriding core and community classes, by just copying the directory structure and matching the class name. Needless to say that this is a terrible practice, but it is still useful to know about just in case you someday have to take care of a project that exploits this behavior. Routing and request flow Before going into more detail about the different components that form a part of Magento, it is important that we understand how these components interact together and how Magento processes requests coming from the web server. As with any other PHP application, we have a single file as an entry point for every request; in the case of Magento this file is index.php, which is in charge of loading the Mage.php bootstrap class and starting the request cycle. It then goes through the following steps: The web server receives the request and Magento is instantiated by calling the bootstrap file, Mage.php. The frontend controller is instantiated and initialized; during this controller initialization Magento searches for the web routes and instantiates them. Magento then iterates through each of the routers and calls the match. The match method is responsible for processing the URL and generating the corresponding controller and action. Magento then instantiates the matching controller and takes the corresponding action. Routers are especially important in this process. The Router objects are used by the frontend controller to match a requested URL (route) to a module controller and action. By default, Magento comes with the following routers: Mage_Core_Controller_Varien_Router_Admin Mage_Core_Controller_Varien_Router_Standard Mage_Core_Controller_Varien_Router_Default The action controller will then load and render the layout, which in turn will load the corresponding blocks, models, and templates. Let's analyze how Magento will handle a request to a category page; we will use http:// localhost/catalog/category/view/id/10 as an example. Magento URIs are comprised of three parts – /FrontName/ControllerName/ActionName. This means that for our example URL, the breakdown would be as follows: FrontName: catalog ControllerName: category ActionName: view If I take a look at the Magento router class, I can see the Mage_Core_Controller_ Varien_Router_Standard match function: public function match(Zend_Controller_Request_Http $request){…$path = trim($request->getPathInfo(), '/');if ($path) {$p = explode('/', $path);} else {$p = explode('/', $this->_getDefaultPath());}…} From the preceding code, we can see that the first thing the router tries to do is to parse the URI into an array. Based on our example URL, the corresponding array would be something like the following code snippet: $p = Array([0] => catalog[1] => category[2] => view) The next part of the function will first try to check if the request has the module name specified; if not, then it tries to determine the module name based on the first element of our array. And if a module name can't be provided, then the function will return false. Let's take a look at that part of the code: // get module nameif ($request->getModuleName()) {$module = $request->getModuleName();} else {if (!empty($p[0])) {$module = $p[0];} else {$module = $this->getFront()->getDefault('module');$request->setAlias(Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, '');}}if (!$module) {if (Mage::app()->getStore()->isAdmin()) {$module = 'admin';} else {return false;}} Next, the match function will iterate through each of the available modules and try to match the controller and action, using the following code: …foreach ($modules as $realModule) {$request->setRouteName($this->getRouteByFrontName($module));// get controller nameif ($request->getControllerName()) {$controller = $request->getControllerName();} else {if (!empty($p[1])) {$controller = $p[1];} else {$controller =$front->getDefault('controller');$request->setAlias(Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS,ltrim($request->getOriginalPathInfo(), '/'));}}// get action nameif (empty($action)) {if ($request->getActionName()) {$action = $request->getActionName();} else {$action = !empty($p[2]) ? $p[2] :$front->getDefault('action');}}//checking if this place should be secure$this->_checkShouldBeSecure($request,'/'.$module.'/'.$controller.'/'.$action);$controllerClassName = $this->_validateControllerClassName($realModule, $controller);if (!$controllerClassName) {continue;}// instantiate controller class$controllerInstance = Mage::getControllerInstance($controllerClassName,$request, $front->getResponse());if (!$controllerInstance->hasAction($action)) {continue;}$found = true;break;}... Now that looks like an awful lot of code, so let's break it down even further. The first part of the loop will check if the request has a controller name; if it is not set, it will check our parameter array's ($p) second value and try to determine the controller name, and then it will try to do the same for the action name. If we got this far in the loop, we should have a module name, a controller name, and an action name, which Magento will now use to try and get a matching controller class name by calling the following function: $controllerClassName = $this->_validateControllerClassName($realModule, $controller); This function will not only generate a matching class name but it will also validate its existence; in our example case this function should return Mage_Catalog_ CategoryController. Since we now have a valid class name, we can proceed to instantiate our controller object; if you were paying attention up to this point, you have probably noticed that we haven't done anything with our action yet, and that's precisely the next step in our loop. Our new instantiated controller comes with a very handy function called hasAction(); in essence, what this function does is to call a PHP function called is_callable(), which will check if our current controller has a public function matching the action name; in our case this will be viewAction(). The reason behind this elaborate matching process and the use of a foreach loop is that it is possible for several modules to use the same FrontName. Now, http://localhost/catalog/category/view/id/10 is not a very user-friendly URL; fortunately, Magento has its own URL rewrite system that allows us to use http: //localhost/books.html. Let's dig a little deeper into the URL rewrite system and see how Magento gets the controller and action names from our URL alias. Inside our Varien/Front.php controller dispatch function, Magento will call: Mage::getModel('core/url_rewrite')->rewrite(); Before actually looking into the inner workings of the rewrite function, let's take a look at the structure of the core/url_rewrite model: Array (["url_rewrite_id"] => "10"["store_id"] => "1"["category_id"] => "10"["product_id"] => NULL["id_path"] => "category/10"["request_path"] => "books.html"["target_path"] => "catalog/category/view/id/10"["is_system"] => "1"["options"] => NULL["description"] => NULL) As we can see, the rewrite module is comprised of several properties, but only two of them are of particular interest to use – request_path and target_path. Simply put, the job of the rewrite module is to modify the request object path information with the matching values of target_path.
Read more
  • 0
  • 0
  • 2314

article-image-article-decider-external-apis
Packt
11 Jun 2013
22 min read
Save for later

The Decider: External APIs

Packt
11 Jun 2013
22 min read
(For more resources related to this topic, see here.) Using an external API APIs are provided as a service from many different companies. This is not an entirely altruistic move on the part of the company. The expectation is that by providing the information and access to the company's data, the company gets more usage for their service and more customers. With this in mind, most (if not all) companies will require you to have an account on their system in order to access their API. This allows you to access their systems and information from within your application, but more importantly from the company's perspective, it allows them to maintain control over how their data can be used. If you violate the company's usage policies, they can shut off your application's access to the data, so play nice. The API key Most APIs require a key in order to use them. An API key is a long string of text that gets sent as an extra parameter on any request you send to the API. The key is often composed of two separate pieces and it uniquely identifies your application to the system much like a username and a password would for a regular user account. As such it's also a good idea to keep this key hidden in your application so that your users can't easily get it. While each company is different, an API key is typically a matter of filling out a web form and getting the key. Most companies do not charge for this service. However, some do limit the usage available to outside applications, so it's a good idea to look at any restrictions the company sets on their service. Once you have an API key you should take a look at the available functions for the API. API functions API functions typically come in two types – public and protected: The public functions can simply be requested with the API key The protected functions will also require that a user be logged into the system in order to make the request If the API function is protected, your application will also need to know how to log in correctly with the remote system. The login functions will usually be a part of the API or a web standard such as Facebook and Google's OAuth. It should be noted that while OAuth is a standard, its implementation will vary depending on the service. You will need to consult the documentation for the service you are using to make sure that the features and functions you need are supported. Be sure to read through the service's API documentation to understand which functions you will need and if they require a login. Another thing to understand about APIs is that they don't always do exactly what you need them to do. You may find that you need to do a little more work than you expect to get the data you need. In this case, it's always good to do a little bit of testing. Many APIs offer a console interface where you can type commands directly into the system and examine the results: Image This can be really helpful for digging into the data, but consoles are not always available for every API service. Another option is to send the commands in your application (along with your API credentials) and examine the data returned in the Safari console. The drawback of this method is that the data is often returned as a single-line string that is very difficult to read as shown in the screenshot: Image This is where a tool like JSONLint comes in handy. You can copy and paste the single-line string from your Safari console into the page at http://jsonlint.com and have the string formatted so that it is much easier to read and validate the string as JSON at the same time: Image Once you get a hold of what data is being sent and received, you will need to set it all up in Sencha Touch. External APIs and Sencha Touch As we have talked about earlier in the book, you cannot use a standard AJAX request to get data from another domain. You will need to use a JSONP proxy and store to request data from an external API. Using the API or the Safari console, you can get a good idea of the data that is coming back to you and use it to set up your model. For this example, let's use a simple model called Category. code We can then set up a store to load data from the API: This will set up a store with our Category model and call the url property for our external API. Remember that we have to send our credentials along with the request so we set these as extraParams on the proxy section. The apiKey and appSecret properties shown here are examples. You will need your own API key information to use an API. We also need to set a property called rootProperty in the reader section. Most API's send back a ton of detailed information along with the request and the store needs some idea of where to start loading in the category records. We can also add additional parameters later by calling the setExtraParam() function on our store proxy. This will let us add additional parameters to be sent to our external API URL. Please note that setExtraParam() will add an additional parameter but setExtraParams() will replace all of our extraParams with the new values. The basic application The Decider application is designed to use a combination of local storage, Google's Map API, and the Foursquare API. The application will take a list of people and their food preferences, and then use Foursquare and Google Maps to find nearby places to eat that will match everyone's food preferences. This screenshot provides a pictorial representation of the preceding explanation: Image Our contacts and categories will be stored using local storage. External APIs from Google and Foursquare will generate our maps and restaurant listings respectively. We will start with a quick overview of the basic application structure and forms, before diving into the store setup and API integration. Our main container is a simple card layout: code In this viewport we will add two cards: a navigation view and a form panel. Our navigationvew will serve as our main window for display. We will add additional containers to it via our controller: code This mainView contains our navigationBar and our homeScreen container with the big Get Started button. This button will add new containers to the navigation view (we will look at this later in the controller). A DataStage project stores jobs and define their environment, such as their security and execution resources. Your project, as well as your user account, is typically created by your DataStage administrator. The second item that is added to our viewport is our form panel. This will contain text fields for first and last name, as well as a selectable list for our different food categories: code We close out the form with a segmentedbutton property, which has options for Save and Cancel. We will add the handler functions for these buttons later on in our controller. We also include a title bar at the top of the form to give the user some idea of what they are doing. One of the key pieces of this form is the categories list, so let's take a closer look at how it works. Creating the categories list Since we will be getting our list of potential restaurants from the Foursquare API, we need to use their categories as well so that we can match things up with some degree of accuracy. The Foursquare API can be found at https://developer.foursquare.com/. As mentioned before, you will need a Foursquare account to access the API. You will also need an API key in order to integrate Foursquare with your application. We can use the Foursquare's API to get a list of categories, however the API returns a list of a few hundred categories including Airports, Trains, Taxis, Museums, and Restaurants. Additionally, each of these has its own subcategories. All we really want is the subcategories for Restaurants. To make things more complicated, Foursquare's API also returns the data like this: code This means we can only get at a specific category by its order in the array of categories. For example, if Restaurants is the twenty-third category in the array, we can get to it as: categories[23], but we cannot get to it by calling categories['Restaurants']. Unfortunately, if we use categories[23] and Foursquare adds a new category or changes the order, our application will break. This is a situation where it pays to be adaptable. Foursquare's API includes a console where we can try out our API requests. We can use this console to request the data for all of our categories and then pull the data we need into a flat file for our application. Check this URL to see the output: https://developer.foursquare.com/docs/explore#req=venues/categories We can copy just the Restaurant information that we need from categories and save this as a file called categories.json and call it from our store. A better solution to this conundrum would be to write some server code that would request the full category list from Foursquare and then pull out just the information we are interested in. But for the sake of brevity, we will just use a flat json file. Each of our categories are laid out like this: code The main pieces we care about are the id, name, shortname and icon values. This gives us a data model that looks like this: code Notice that we also add a function to create an image URL for the icons we need. We do this with the convert configuration, which lets us assemble the data for image URL based on the other data in the record: code The convert function is automatically passed both the data value (v), which we ignore in this case, and the record (rec), which lets us create a valid Foursquare URL by combining the icon.prefix value, a number, and the icon.suffix value in our record. If you take a look at our previous category data example, this would yield a URL of: https://foursquare.com/img/categories_v2/food/argentinian_32.png By changing the number we can control the size of the icon (this is part of the Foursquare API as well). We combine this with our XTemplate: code This gives us a very attractive list for choosing our categories: Images Next we need to take a look at the controller for the contact form. Creating the contact controller The contact controller handles saving the contact and canceling the action. We start out the controller by declaring our references and controls: code Remember that our refs (references) provide a handy shortcut we can use anywhere in the controller to get to the pieces we need. Our control section attaches tap listeners to our cancel and save buttons. Next we need to add our two functions after the controls section. The doCancel function is really simple: code We just use our references to clear the contact editor, deselect all the items in our category list, and switch back to our main view. The save function is a little more complex, but similar to the functions we have covered elsewhere in this book: code As with our previous save functions, we create a new MyApp.model.Contact and add the values from our form. However, since our list isn't really a standard form component we need to grab its selections separately and add them to the contact data as a comma-separated list. We do this by creating an empty array and using Ext.each() to loop through and run a function on all our categories. We then use join to implode the array into a comma-separated list. Finally, we save the contact and run our doCancel function to clean up and return to our main view. Now that we can add contacts we need to create a controller to handle our requests to the Foursquare and Google APIs, and get the data back to our users. Integrating with Google Maps and Foursquare Our application still has a couple of tasks to accomplish. It needs to: Handle the click of the Get Started button Add our maps panel and offer to adjust the current location via Google Maps API Display a list of friends to include in our search Display the search results in a list Display the details for a selected result We will start out with the basic skeleton of the controller, create the views and stores, and then finish up the controller to complete the application. Starting the mainView.js controller We will start the mainView.js controller file with some placeholders for the stores. We will add views later on and some references for those components. Keep in mind that when working with placeholders in this fashion the application will not be testable until all the files are actually in place. We create the mainView.js file in our controllers folder: code At the top of this configuration we require Ext.DateExtras. This file provides us with formatting options for date objects. If this file is not included, only the now() method for date objects will be available in your application. In our views section we have added placeholders for confirmLocation, restaurantList, friendChooser,and restaurantDetails. We will add these files later on, along with the RestaurantStore file listed in our stores section. We also have a number of references for these views, stores, and some of their sub-components. We will need to create these views before getting to the rest of our controller. We will take these views in the order the user will see them, starting with the confirmLocation view. Creating the confirmLocation view The confirmLocation view first appears when the user clicks on the Get Started button. This view will present the user with a map showing their current location and offer an option to switch to a different location if the user desires. The following screenshot gives a pictorial representation of the preceding code: Image In order to give ourselves a bit more flexibility, we will be using the Google Maps Tracker plugin as part of this view. You can find this plugin in your Sencha Touch 2 folder in examples/map/lib/plugin/google/Tracker.js. Copy the file into a lib/google folder in your main application folder and be sure to add it into the requires section of your app.js file: code This plugin will let us easily drop markers on the map. Once the Google Tracker plugin file is included in the application, we can set up our confirmLocation.js view like so: code The view itself is a simple container with some HTML at the top asking the user to confirm their location. Next we have a map container that uses our Google Tracker plugin to configure the map and animate the location marker to drop from the top of the screen to the current location of the user. The position configuration is a default location, which is used when the user denies the application access to their current location. This one is set to the Sencha Headquarters. Next we need a few options for the user to choose from: Cancel, New Location, and Next. We will add these as a segmented button under our map container. We add the code to the end of our items container (after the map container): code Each of our buttons has an associated action. This allows us to assign functions to each button within the mainView.js controller. By creating buttons in this fashion, we maintain separation between the display of the application and the functionality of the application. This is really helpful when you want to re-use a view component. The next view the user encounters is the Friends Chooser. Creating the Friends Chooser view The friendsChooser.js file uses a similar list to our previous category chooser. This lets our users select multiple people to include in the restaurant search: Image Our friendChooser extends the Ext.Container component and allows the user to select from a list of friends: code As with our previous panel, we have a container with HTML at the top to provide some instructions to the user. Below that is our list container, which, like our category list, allows for selection of multiple items via the mode: 'MULTI' configuration. We also set grouped to true. This allows our store to group the contacts together by last name. If you take a look at the ContactStore.js file, you can see where we do: code This configuration returns the first letter of the last name for grouping. The last thing we need to do with our friendChooser.js file is add the buttons at the bottom to Cancel or Finish the search. The buttons go out in the items section, just below the list: code As in our previous view, we use a segmentedbutton property with actions assigned to each of our individual buttons. Once the user clicks on Finish, we will need to return a list of restaurants they can select from. Creating the restaurant list, store, and details Our restaurant list will use a store and the Foursquare API to return a list of restaurants based on the shared preferences of everyone the user selected. The following screenshot exemplifies the preceding explanation: Image This component is pretty basic: code This component uses a simple list with a configuration option for onItemDisclosure:true. This places an arrow next to the restaurant name in the list. The user will be able to click on the arrow and see the details for that restaurant (which we will create after the store). We also set grouped to true, only this time our store will use a function to calculate and sort by distance. Creating the restaurant store and model The restaurant store is where we set up our request to the Foursquare API: code The RestaurantStore.js file sets a model and storeId field for our store and then defines our proxy. The proxy section is where we set up our request to Foursquare. As we mentioned at the start of the article, this needs to be a jsonp request since it is going to another domain. We make our request to https://api.foursquare. com/v2/venues/search and we are looking for the responses.venues section of the JSON array that gets returned. You will note that this store currently has no other parameters to send to Foursquare. We will add these later on in the controller before we load the store. For the model, we can consult the Foursquare API documentation to see the information that is returned for a restaurant (called a venue in Foursquare terms) at https://developer.foursquare.com/docs/responses/venue You can include any of the fields listed on the page. For this app, we have chosen to include the following code in our model: code You can add more fields if you want to display more information in the details view. Creating the details view The details view is a simple panel and XTemplate combination. Using our controller, the panel will receive the data record when a user clicks on a restaurant in the list: code Since the tpl tag is basically HTML, you can use any CSS styling you like here. Keep in mind that certain fields such as contact, location, and categories can have more than one entry. You will need to use <tpl for="fieldname"> to loop through these values. Now that the views are complete, we need to head back to our controller and add the functions to put everything together. Finishing the main view controller When we started out with our main controller, we added all of our views, stores, and references. Now it's time to add the functionality for the application. We start by adding a control section to the end of our config: code The controls are based on the references in the controller and they add functions to specific listeners on the component. These are each in the format of: code Once these controls are in place, we can add our functions after the config section of our controller. Our first function is doStart. This function loads our Contacts store and checks to see if we have any existing contacts. If not, we alert the user and offer to let them add some. If they have contacts we create a new instance of our confirmLocation container and push it onto the main navigation view: code Remember that since the mainView is a navigation view, a Back button will automatically be created in the top toolbar. This function will show the user our initial map panel with the users current location. This panel needs four functions: one to cancel the request, one to pop up a new location window, one to set the new location, and one to move on to the next step: code We actually want to be able to use the doCancel function from anywhere in the process. As we add new panels to our mainView navigation, these panels simply pile up in a stack. This means we need to get the number of panels currently on the mainView stack. We use length-1 to always leave the initial panel (the one with our big Get Started button) on the stack. We use pop to remove all but the first panel from the stack. This way the Cancel button will take us all the way back to the beginning of our stack, while the Back button will take us back just to the previous step. The next function is doNewLocation(), which uses Ext.Msg.prompt to ask the user to enter a new location: code If the user enters a new location, we call setNewLocation to process the text the user entered in the prompt textbox: code This code gets our map and encodes the text the user passed us as a geocode location. If Google returns a valid address, we center the map on the location and drop a marker to show the exact location. We also set the latitude and longitude so that we can reference them later. If we fail to get a valid address, we alert the user so they can fix it and try again. Once the user is happy with the location they can click on the Next button, which fires our doChooseFriends function: This function pushes our friendchooser view onto the stack for display. The friendchooser view allows the user to select multiple friends and click on Cancel or Finish. Since we have already taken care of our Cancel button with our doCancel function, we just need to write the doShowRestaurants function. This function starts by looping through the selected friends. For the first one in the list, we grab the restaurant categories we have stored for the friend and convert it from a comma-separated list (which is how we stored it) into an array. This lets us grab every subsequent selection and run Ext.Array.intersect() to find the common categories between all of the selected friends: code Next, we load the store based on the common categories by categoryID, the location data we have stored in our map, client_id, and client_secret that comprise our API key for Foursquare and a radius value (in meters). We also send a required field called v that is set to the current date. Finally, we push our restaurant list component onto the stack of containers. This will display our list of results and allow the user to click on for details. This brings us to our doShowRestaurantDetails function: code When the user taps one of the disclosure icons in our list of restaurants, we push a restaurantdetails view onto the stack of containers and set its data to the record that was tapped. This displays the details for the restaurant in our details XTemplate Homework There are a number of additional features that can be added to this type of application, including: Editing for contacts (or automatically pulling friends from Facebook) Setting up a live feed for the categories menu Adding additional venues other than restaurants Combining the application with additional APIs such as Yelp for reviews Just remember the key requirements of using additional APIs: the API key(s), studying the API documentation, and using the JSONP store for grabbing the data. Summary In this article we talked about using external APIs to enhance your Sencha Touch applications. This included: An overview of API basics Putting together the basic application Interaction with Google Maps and Foursquare Building the views, models, and stores Building the application controller Resources for Article : Further resources on this subject: How to Use jQuery Mobile Grid and Columns Layout [Article] iPhone JavaScript: Installing Frameworks [Article] An Introduction to Rhomobile [Article]
Read more
  • 0
  • 0
  • 5524
Modal Close icon
Modal Close icon