Part III: The Workbench
|
Tuesday, October 20, 2009
Part III: The Workbench
Section 27.7. Variables
27.7. Variables
This plug-in provides classes and interfaces to support the definition and contribution of variables for the purpose of string substitution. It supports the recursive replacement of variables referenced by name in arbitrary strings with the value of the variable. Two types of variables are provided: value variables (IValueVariable) and dynamic variables (IDynamicVariable). A value variable has a simple setter and getter for its value. A dynamic variable has an associated resolver that provides a variable's value each time it is referenced (replaced) in a string substitution. A dynamic variable may also provide an argument in its reference, which can be used by its resolver to determine its substitution value. A variable manager (IStringVariableManager) is provided to manage the set of defined variables. Value variables may be created via API on the variable manager, or contributed via the valueVariables extension point. Dynamic variables must be contributed via the dynamicVariables extension point. The variable manager provides change notification for value variables and an API for performing string substitution. Substitution simply takes a string containing variable patterns and returns that string with all the variables replaced by their associated variable values. Variables are referenced in strings by enclosing them in braces, preceded with a dollar sign. For example, "abc${foo}ghi" is composed of the strings "abc" and "ghi" sandwiching the variable "foo". If the value of foo is "def", string substitution gives "abcdefghi". In the case of dynamic variables, an optional argument is supplied by appending a colon and argument value after the variable name, for example, "${foo:bar}". In this case, the resolver associated with foo is given the referenced argument, bar, when asked to resolve a value for the variable foo. |
Other Distributions
Other DistributionsFedora, Mandrake, and SuSE are the distributions discussed in this book. Other popular major distributions include the following:
The database at DistroWatch currently includes over 300 active distributions. Most distributions are modifications of Red Hat/Fedora or Debian. If you have a specific purpose for your Linux, you can probably find a distribution that provides what you need. |
Default Values
Default Values
You will need to define the constant DEFAULT_IGNORE_REASON in the TestRunner class to be whatever string you desire:
You can supply a default value on any annotation type member. The default must be a constant at compile time. The new definition of @Ignore includes a default value on the reasons member. Note use of the keyword default to separate the member signature from the default value.
|
Optimizing Mathematical Calculations
Optimizing Mathematical Calculations
Assembly language presents an efficient way for
optimizing mathematical operations, and also the operations for data
array processing and hardware interaction. Most of the applications
make intensive use of mathematical calculations, and assembly language
is often a good way to optimize the performance of these calculations.
For creating highly efficient applications, the crucial factor is
expertise in the Floating-Point Unit (FPU) hardware and program
architecture, as well as in the SIMD technology.
In this chapter, we will focus on the principles of the
FPU operation and the options for application optimization. Practical
examples of how to make use of the FPU features will be considered in Chapter 2.
Using the Floating-Point Unit (FPU)
The earliest models of Intel processors did not
have hardware support for the floating-point operations. All operations
of this kind were implemented as procedures made up of the ordinary
mathematical commands. For early models, a special additional chip was
developed, which got the name of mathematical coprocessor.
It included the commands enabling the computer to perform the
floating-point operations much faster than was done by the procedures
containing ordinary mathematical commands.
Starting from the 486DX processors, the mathematical
coprocessor no longer exists as a separate device. Instead, the
processors contain the FPU, but it is programmed as a separate module.
The FPU program model can be described as a combination of the
following registers:
FPU stack registers. There are 8 of them, and their names are ST(0), ST(1), ST(2) … ST(7). The floating-point numbers are stored as 80-bit numbers of the extended format. The ST(0) register always points to the top of the stack. As the numbers are received by the FPU, they are added on top of the stack.
Control/status registers. These include the
status register reflecting the information on the processor status, the
control register (for controlling the FPU operation modes), and the tag
status register that reflects the status of the ST(0)…ST(7) registers.
Data point register and instruction point register. These are intended for processing the exceptions.
Any of the registers listed above can be accessed by
the program either directly or indirectly. In FPU programming, the most
frequently used elements are the ST(0)…ST(7) registers and the C0, C1, C2, and C3 bits of the status register.
The FPU registers operate as an ordinary stack of the
CPU. But this stack has a limited number of positions—only 8 of them.
The FPU has one more register, which is difficult for the programmer to
access. This is a word containing the “labels” of each of the stack
positions. This register enables the FPU to trace, which of the stack
positions are currently in use and which are not engaged. Any attempt
to place an object into a stack position that is already engaged
creates an exception.
To place the data into the FPU stack, the program uses
the load command that places the data on top of the stack. If a number
stored in memory has a format other than the temporary float format,
then (during the loading) the FPU converts this number to the 80-bit
form.
The write commands extract the values from the FPU
stack and place them into memory. If data format conversion is needed,
it is performed as part of the write operation. Some forms of the write
operation leave the top of the stack intact for further operations.
After being placed into the FPU stack, the data can be
accessed and used by any command. The processor instructions allow both
the operations between the registers and the operations between the
memory and the registers. In the same way as in the CPU, between any
two operands, one should be stored in a register. For the FPU, one of
the operands should always be a top element of the stack, and another
operand may be taken either from the memory or from the stack of
registers.
Any arithmetic operation should always have the
stack of registers as the destination. The FPU, being a processor unit
for numeric operations, cannot write the result into memory by using
the same command that performed the calculations. To send the operand
back to the memory, it is necessary to use either a separate write
command or a command that extracts data from the stack and then writes
it into memory.
FPU Commands
All FPU commands start with the F letter to be distinguished from the CPU commands. The FPU commands can be conventionally arranged into several groups:
Data transfer commands
Addition and subtraction commands
Multiplication and division commands
Comparison commands
Transcendental functions commands
Control flow commands
The FPU provides the developer with hardware-level
support for the algorithms that calculate trigonometric functions,
logarithms, and powers. Such calculations are entirely transparent for
the software developer and do not require writing any additional
algorithms.
The FPU makes it possible to perform mathematical
calculations with very high precision level (up to 18 digits). If you
perform such calculations without using the FPU functions, the result
will be less precise.
The use of assembly language for FPU programming can
give you considerable gain in application performance. This is because
the system of FPU instructions contains different groups of commands,
providing the developer with virtually all the tools for implementing
most calculation algorithms. Even if some of the needed commands are
missing, you can easily find an equivalent operation made up of several
assembly instructions. It should be noted that by programming the FPU
with assembly commands, you could implement even the operations that
are difficult or even impossible to write in C++.
With regard to mathematical functions in the C++
standard libraries, we need to note that their assembly analogs often
let you obtain an even higher performance, as well as a smaller program
size. Assembly language also lets developers create custom functions,
which often appear more efficient than their analogs from the
mathematical library in Visual C++ .NET.
Adapter
| ||||||||||
Adapter
This pattern was previously described in [GoF95].
Synopsis
An adapter class implements an interface known to its clients and provides access to an instance of a class not known to its clients. An adapter object provides the functionality promised by an interface without having to assume what class is used to implement that interface.
Context
Suppose that you are writing a method that copies an array of objects. The method is supposed to filter out objects that do not meet certain criteria, so that the copied array may not contain all of the elements in the original array. To promote reuse, you want the method to be independent of the filtering criteria being used. You can do this by defining an interface that declares a method the array copier can call to find out whether it should include a given object in the new array, as shown in Figure 7.1
Figure 7.1: Simple copy filter.1
In Figure 7.1, an ArrayCopier class delegates to the CopyFilterIF interface the decision to copy an element from the old array to the new array. If the isCopyable method returns true for an object, then the object is copied to the new array.
This solution solves the immediate problem of allowing the copy criteria used by ArrayCopier objects to be encapsulated in a separate object without having to be concerned about what the object’s class is. This solution presents another problem. Sometimes the logic needed for filtering is in a method of the objects being filtered. If these objects do not implement the CopyFilterIF interface, then the ArrayCopier object cannot directly ask these objects whether they should be copied. However, the ArrayCopier object can indirectly ask the filtered objects whether they should be copied, even if they do not implement the CopyFilterIF interface.
Suppose a class called Document has a method called isValid that returns a boolean result. You want an ArrayCopier object to use the result of isValid to filter a copy operation. Because Document does not implement the CopyFilterIF interface, an ArrayCopier object cannot directly use a Document object for filtering. Another object that does implement the CopyFilterIF interface cannot independently determine whether a Document object should be copied to a new array. It does not work because it has no way to get the necessary information without calling the Document object’s isValid method. The answer is for that object to call the Document object’s isValid method, resulting in the solution shown in Figure 7.2.
Figure 7.2: Copy filter adapter.
In this solution, the ArrayCopier object, as always, calls the isCopyable method of an object that implements the CopyFilterIF interface. In this case, the object is an instance of the DocumentCopyFilterAdapter class. The DocumentCopyFilterAdapter class implements the isCopyable method by delegating the call to the Document object’s isValid method.
Forces
| You want to use a class that calls a method through an interface, but you want to use it with a class that does not implement the interface. Modifying the class to implement the interface is not an option either because |
| You do not have the source code for the class. |
| The class is a general-purpose class and it would be inappropriate for it to implement an interface for a specialized purpose. |
| You want to dynamically determine which of another object’s methods an object calls without the object having knowledge of the other object’s class. |
Solution
Suppose you have a class that calls a method through an interface. You want an instance of this class to call a method of an object that does not implement the interface. You can arrange for the instance to make the call through an adapter object that implements the interface by delegating the calls to a method of the object that doesn’t implement the interface. The diagram in Figure 7.3 shows how this works.
Here are the roles that the classes and interface play in Figure 7.3:
Figure 7.3: Adapter.
Client. A class in this role calls a method of another class through an interface to avoid assuming the actual class that implements the method.
TargetIF. An interface in this role declares a method that the client class calls.
Adapter. A class in this role implements the TargetIF interface. It implements the method that the Client calls by delegating the call to a method of the Adaptee class, which does not implement the TargetIF interface.
Adaptee. A class in this role does not implement the TargetIF method but has a method that the Client class wants to call.
It is possible for an Adapter class to do more than simply delegate a method call. It may perform some transformation on the arguments. It may provide additional logic to hide differences between the intended semantics of the interface’s method and the actual semantics of the Adaptee class’s method. There is no limit to how complex an adapter class can be. So long as the essential purpose of the class is as an intermediary for method calls to one other object, you can consider it to be an adapter class.
Implementation
Implementation of the adapter class is rather straightforward. However, an issue you should consider when implementing the Adapter pattern is how the Adapter objects will know which instance of the Adaptee class to call. There are two approaches.
| Pass a reference to the Adaptee object as a parameter to the adapter object’s constructor or one of its methods. This allows the Adapter object to be used with any instance or possibly multiple instances of the Adaptee class. This approach is illustrated in the following example: |
class CustomerBillToAdapter implements AddressIF { | |
| Make the adapter class an inner class of the Adaptee class. This simplifies the association between the adapter object and the Adaptee object by making it automatic. It also makes the association inflexible. This approach is illustrated in the following example: |
|
Java allows class declarations to be nested, like this:
public class Foo {
private int x;
...
class Bar {
void increment() {
x = x+1;
} // increment()
...
} // class bar
} // class foo
Because the Bar class is defined inside of the Foo class, it is considered to be part of the Foo class. Because it is part of the Foo class, it can refer to the Foo class’s private instance variables. When an instance of the Foo class creates an instance of the Bar class, the instance of Foo that created the Bar object is called the Bar object’s enclosing instance. Any references in the Bar class to one of the Foo class’s instance variables will refer to the variables of the enclosing instance.
Inner classes may be private. A private class is accessible to its enclosing class but not to any classes outside of its enclosing class. If a class is needed only to support another class, then the best way to organize the supporting class may be as a private inner class of the class that it supports.
If an object needs to have another object call one of its methods and to do so it passes an adapter object to the other object, then it is appropriate for the adapter object to be an instance of a private inner class.
An inner class may be declared inside of a method. If an inner class is declared inside of a method, then it can access the enclosing class’s instance variables and the enclosing method’s local variables.
Inner classes declared in a method can be anonymous. The second bullet under the Implementation heading shows an example of this. The syntax combines the creation of the class’s instance with the class’s definition. It consists of the word new followed by the name of the class to be extended or an interface to be implemented, the constructor arguments, and then the class body in curly braces.
The example shown in the second bullet under the Implementation heading defines an anonymous inner class that implements the ActionListener interface. It creates an instance of the anonymous class and passes it to the MenuItem object’s addActionListener method.
For more information about inner classes, see Section 8.1.2 of the Java Language Specification at http://java.sun.com/docs/books/jls/second_edition/html/.
Consequences
| The Client and Adaptee classes remain independent of each other. |
| You can use an adapter class to determine which of an object’s methods another object calls. For example, you may have a class whose instances are GUI widgets that allow telephone numbers to be displayed and edited. This class fetches and stores telephone numbers by calling methods defined by an interface. To make use of the interface you define adapter classes. You may have an adapter class to fetch and store a fax number from instances of a class and another adapter class to fetch and store pager numbers from instances of the same class. The difference between the two adapter classes would be that they call different methods of the Adaptee class. Here is an example. Suppose there is a class named PhoneNumberEditor that is responsible for allowing a user to edit a phone number. An object is passed to the constructor of a PhoneNumberEditor that implements this interface. |
public interface PhoneNumberIF { | |
If you want to create two PhoneNumberEditor objects to edit the office and fax numbers of a person, you might write some code that looks like this: | |
PhoneNumberEditor voiceNumber; | |
Each PhoneNumberEditor object is created with a different adapter. Each adapter calls different methods of the same object. | |
| The Adapter pattern adds indirection to a program. Like any other indirection, it contributes to the difficulty involved in understanding the program. |
Java API Usage and Example
A very common way to use adapter classes with the Java API is for event handling, like this:
Button ok = new Button("OK");
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
doIt();
} // actionPerformed(ActionEvent)
} );
add(ok);
The previous example creates an instance of an anonymous class that implements the ActionListener interface. The class’s actionPerformed method is called when the Button object is pressed. This coding pattern is very common for code that handles events.
The Java API does not include any public adapter classes that are ready to use. It does include classes such as java.awt.event.WindowAdapter that are intended to be subclassed rather than used directly. The idea is that some event listener interfaces, such as WindowListener, declare multiple methods that may not all need to be implemented in many cases. The WindowListener interface declares eight methods that are called to provide notification about different kinds of window events. Often only one or two of those event types are of interest. The methods corresponding to events that are not of interest will typically be given do-nothing implementations. The WindowAdapter class implements the WindowListener interface and implements all eight of its methods with do-nothing implementations. An adapter class that subclasses the WindowAdapter class needs to implement only those methods corresponding to events that are of interest. It inherits do-nothing implementations for the rest. For example:
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit();
} // windowClosing(WindowEvent)
} );
In the preceding example, the anonymous adapter class is a subclass of the WindowAdapter class. It only implements the windowClosing method. It inherits do-nothing implementations for the other seven methods from the WindowAdapter class.
Related Patterns
Façade. The Adapter class provides an object that acts as an intermediary for method calls between a client object and one other object not known to the client objects. The Façade pattern provides an object that acts as an intermediary for method calls between its client object and multiple objects not known to the client objects.
Iterator. The Iterator pattern is a specialized form of the Adapter pattern for sequentially accessing the contents of a collection of objects.
Proxy. The Proxy pattern, like the Adapter pattern, uses an object that is a surrogate for another object. However, a Proxy object has the same interface as the object for which it is a surrogate.
Strategy. The Strategy pattern is structurally similar to the Adapter pattern. The difference is in the intent. The Adapter pattern allows a Client object to carry out its originally intended function by calling methods of objects that implement a particular interface. The Strategy pattern provides objects that implement a particular interface for the purpose of altering or determining the behavior of a Client object.
Anonymous Adapter. The Anonymous Adapter pattern (described in Patterns in Java, Volume 2) is a coding pattern that uses anonymous Adapter objects to handle events.
Section 25.112. Event.preventDefault( ): cancel default action of an event
25.112. Event.preventDefault( ): cancel default action of an eventDOM Level 2 Events25.112.1. Synopsis
25.112.2. DescriptionThis method tells the web browser not to perform the default action (if any) associated with this event. For example, if the type property is "submit", any event handler called during any phase of event propagation can prevent form submission by calling this method. Note that if the cancelable property of an Event object is false, either there is no default action or there is a default action that cannot be prevented. In either case, calling this method has no effect. |