Tuesday, October 20, 2009

Part III:  The Workbench










Part III: The Workbench



The Workbench provides the UI building blocks that make Eclipse applications easy to write, easy to use, scalable, and extendable. One of the main advantages of using the Eclipse RCP is the benefit you get from reusing the UI building blocksit allows you to focus on your domain without having to redesign the wheel. This is evident from the fact that the Hyperbola application developed in Part II required relatively little code.


But that work only scratched the surface of what is possible. The Workbench is much more powerful. It is made up of 42 extension points and approximately 350 API classes. It would take an entire book to do justice to the function provided. Rather than attempt a broad partial coverage, the next few chapters focus on the parts of the Workbench that are essential for RCP applications. They dive into their API and use them to solve problems motivated by Hyperbola in various real-world scenarios.


You should come away from this part of the book with a solid understanding of the Workbench's structure and how you can control and customize its operation.














Section 27.7.  Variables










27.7. Variables


Plug-ins

org.eclipse.core.variables

Dependencies

org.eclipse.core.runtime



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 Distributions


Fedora, Mandrake, and SuSE are the distributions discussed in this book. Other popular major distributions include the following:



  • Slackware:
    The oldest surviving Linux distribution. It's most suitable for users who want to learn Linux thoroughly. Slackware has not focused on ease of use. It has no distribution specific utilities or tools. Its strength is consistency, stability, and security, making it very useful for servers. www.slackware.org


  • Debian:
    A pure open source project. Three versions of Debian are available at all times: stable release (the current stable release); testing (contains packages that haven't been accepted into the stable release yetmore cutting-edge, but not as stable); and unstable (the distribution where active development is taking place). Debian has a reputation for being difficult to install unless you know your hardware very well, but it's working to improve the installation procedure. Once it's installed, it's easy to keep up-to-date. www.debian.org


  • MEPIS:
    The newest arrival. MEPIS is based on the Debian distribution. It comes with nonfree applications, such as Java and Macromedia Flash. If you need some of the extra applications it includes, it's much easier to install MEPIS than to install the applications individually on another distribution. www.mepis.org


  • Xandros:
    The easiest Linux of all. It's meant for beginners. Fewer applications are included, but the included applications work well. It's based on Debian, but designed to look as much like Windows as possible. It includes graphical tools designed for Xandros to make tasks, such as file management, easier for the user. www.xandros.org


  • Linspire(formerly named Lindows):
    Another easy Linux, meant for beginners. It features quick and easy installation. It offers a one-click software installation feature that installs software from their own software pool. www.linspire.com


  • Gentoo:
    A source-based Linux. Gentoo emphasizes installing most of your Linux system from source, compiling it on your computer. The installation procedure is more difficult and longer, but the result is a system that's tailored to your hardware and your needs. Gentoo has excellent documentation. www.gentoo.org


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


    The reason for ignoring a test method is likely to be the same most of the time. Most often, you will want to temporarily comment out a test while fixing other broken tests. Supplying a reason each time can be onerous, so you would like to have a default ignore reason. Here's how you might reflect this need in a TestRunner test:




    @TestMethod
    public void ignoreWithDefaultReason() {
    runTests(DefaultIgnoreMethodTest.class);
    verifyTests(methodNameA, methodNameB);
    Map<Method, Ignore> ignoredMethods = runner.getIgnoredMethods();
    Map.Entry<Method, Ignore> entry = getSoleEntry(ignoredMethods);
    Ignore ignore = entry.getValue();
    assert TestRunner.DEFAULT_IGNORE_REASON.
    equals(ignore.reasons()[0]);
    }

    class DefaultIgnoreMethodTest {
    @TestMethod public void testA() {}
    @TestMethod public void testB() {}
    @Ignore(initials=TestRunnerTest.IGNORE_INITIALS)
    @TestMethod public void testC() {}
    }


    You will need to define the constant DEFAULT_IGNORE_REASON in the TestRunner class to be whatever string you desire:



    class TestRunner {
    public static final String DEFAULT_IGNORE_REASON =
    "temporarily commenting out";
    // ...


    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.



    package sis.testing;

    import java.lang.annotation.*;

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Ignore {
    String[] reasons() default TestRunner.DEFAULT_IGNORE_REASON;
    String initials();
    }








      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




















      Chapter 7 -
      Structural Patterns
      Patterns in Java, Volume 1: A Catalog of Reusable Design Patterns Illustrated with UML, Second Edition
      by Mark Grand
      John Wiley & Sons � 2002



























      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




















      J



      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




      l



      You do not have the source code for the class.




      l



      The class is a general-purpose class and it would be inappropriate for it to implement an interface for a specialized purpose.




      L



      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.




















      l



      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 { 
              private Customer myCustomer;

      public CustomerBillToAdapter(Customer customer) {
      myCustomer = customer;
      } // constructor

      public String getAddress1() {
      return myCustomer.getBillToAddress1();
      }

      public void setAddress1(String address1) {
      myCustomer.setBillToAddress1(address1);
      } // setAddress1(String)
      ...
      } // class CustomerBillToAdapter



      l



      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:


       

              MenuItem exit = new MenuItem(caption);
      exit.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
      close();
      } // actionPerformed(ActionEvent)
      } );













      Consequences





























      J



      The Client and Adaptee classes remain independent of each other.




      J



      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 { 
          public String getPhoneNumber() ;

      public void setPhoneNumber(String newValue) ;
      } // 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;
          voiceNumber = new PhoneNumberEditor(new PhoneNumberIF() {
                public String getPhoneNumber() {
                    return person.getOfficeNumber();
                }  // getPhoneNumber
                public void setPhoneNumber(String newValue) {
                    person.setOfficeNumber(newValue);
                }  // setPhoneNumber(String)
      } ) ;

      PhoneNumberEditor faxNumber;
      faxNumber = new PhoneNumberEditor(new PhoneNumberIF() {
                public String getPhoneNumber() {
                    return person.getFAXNumber();
                }  // getPhoneNumber

      public void setPhoneNumber(String newValue) {
                    person.setFAXNumber(newValue);
                } // setPhoneNumber(String)
      } ) ;


       

      Each PhoneNumberEditor object is created with a different adapter. Each adapter calls different methods of the same object.




      L



      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 event


      DOM Level 2 Events



      25.112.1. Synopsis



      void preventDefault( );





      25.112.2. Description


      This 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.