Chapter 4
Shared Components

In this chapter deals with the content of the shared plugin of any Scout application. As the name ”shared already indicates, this plugin contains code and resources that need to be available to both the Scout client and the server application.

The chapter starts with the internationalization of texts in Scout and icon resources. Then, the less visible components are introduced. These include permissions, code types, lookup calls and form data objects.

4.1 Texts / i18n / NLS Support

needs text

Existing Documentation

4.2 Icons

needs text

Existing Documentation

4.3 Code Types and Codes

Code types and codes are widely used in business applications. In general, any fixed set of named entities can be seen as a code type. Code types can be used to model the organisational structure of companies, to represent business units or to categorise or segment entities. Frequently, enumerations or enumerated types1 are used as synonyms for code types. The individual named entities in a code type are called codes in Scout.

Both code types and codes have associated names (translated texts) and IDs. As in the case of standard Java enumerations, Scout codes can also have associated values. A set of additional features enhances Scout code types over simple Java enumerations:

The text below first introduces the basic features of code types and codes using a simple example with static codes. Then, hierarchical code types and the dynamic loading of codes from external sources is explained.

4.3.1 A Simple Example

As a simple example we assume that an event managing organization works with an application to plan events for customers. To distinguish public and private events it is natural to define a corresponding code type. Both the code type and all its elements will have an assigned ID and associated translated texts. See Listing 4.1 for a possible implementation of such a code type.


Listing 4.1: A code type with associated codes.
 
import org.eclipse.scout.rt.shared.TEXTS; 
import org.eclipse.scout.rt.shared.services.common.code.AbstractCode; 
import org.eclipse.scout.rt.shared.services.common.code.AbstractCodeType; 
 
/** 
* @author mzi 
*/ 
public class EventTypeCodeType extends AbstractCodeType<Long, Long> { 
 
 private static final long serialVersionUID = 1L; 
 public static final Long ID = 10000L; 
 
 public EventTypeCodeType() throws ProcessingException { 
   super(); 
 } 
 
 @Override 
 protected String getConfiguredText() { 
   return TEXTS.get(EventType); 
 } 
 
 @Override 
 public Long getId() { 
   return ID; 
 } 
 
 @Order(10.0) 
 public static class PublicCode extends AbstractCode<Long> { 
 
   private static final long serialVersionUID = 1L; 
   public static final Long ID = 10010L; 
 
   @Override 
   protected String getConfiguredText() { 
    return TEXTS.get(Public); 
   } 
 
   @Override 
   public Long getId() { 
    return ID; 
   } 
 } 
 
 @Order(20.0) 
 public static class PrivateCode extends AbstractCode<Long> { 
 
   private static final long serialVersionUID = 1L; 
   public static final Long ID = 10020L; 
 
   @Override 
   protected String getConfiguredText() { 
    return TEXTS.get(Private); 
   } 
 
   @Override 
   public Long getId() { 
    return ID; 
   } 
 } 
}

The code type class and its codes shown in Listing 4.1 have been created using the creation wizards provided by the Scout SDK as described in Section ??. In Scout, code type classes are derived from class AbstractCodeType<CODE_TYPE_ID, CODE_ID>. In the provided example, both the code type ID and the code ID are typed with Long. The value of the event code type ID is assigned by Long ID = 10000L. The contained codes for public and private events are realized by the inner classes PublicCode and PrivateCode that are derived from Scout’s AbstractCode<CODE_ID> class. Their individual IDs then have assigned the numbers 10010 and 10020 respectively. This pattern follows the convention to leave an ample number space between any two code type IDs. This space can then be used for the individual codes of a code type that need ID values as well.

In the above example the types for the ID values are defined by the generic parameter <Long>. And other classes from the package java.lang work well too. In fact, any Java class may be used as a key type for code types and codes as long as it satisfies the following requirements:


Listing 4.2: A codes that is set to inactive.
 
 
   @Override 
   public Long getId() { 
    return ID; 
   } 
 } 
 
 @Order(30.0) 
 public static class ExternalCode extends AbstractCode<Long> { 
 
   private static final long serialVersionUID = 1L; 
   public static final Long ID = 10030L; 
 
   @Override 
   protected boolean getConfiguredActive() { 
    return false; 
   } 
 
   @Override 
   protected String getConfiguredText() { 
    return TEXTS.get(External);

To allow for language specific translations, the configuration method getConfiguredText is used for both the names of code types and codes. A frequently used code property is the active flag to mark obsolete codes. Setting individual codes to inactive is useful for codes that are still linked with existing data but should not longer be used when entering new data into the application. As shown in Listing 4.2, codes can be marked inactive by returning false in method getConfiguredActive.

A set of additional code properties is available to control the appearance of individual codes. Clicking on an individual code in the Scout Explorer provides the list in the Scout Object Property view.

4.3.2 Hierarchical Code Types

To explain the definition and use of hierarchical codes we use the Industry Classification Benchmark as a concrete example. The Industry Classification Benchmark or ICB2 allows to hierarchically classify companies and organisations into industries, super sectors, sectors and sub sectors. Each organizational level has a unique number assigned and a name. This setup can easily be transferred to a hierarchical Scout code type.


Listing 4.3: A hierarchical code type for the Industry Classification Benchmark.
 
 
import org.eclipse.scout.commons.annotations.Order; 
import org.eclipse.scout.commons.exception.ProcessingException; 
import org.eclipse.scout.rt.shared.TEXTS; 
import org.eclipse.scout.rt.shared.services.common.code.AbstractCode; 
import org.eclipse.scout.rt.shared.services.common.code.AbstractCodeType; 
 
public class IndustryICBCodeType extends AbstractCodeType<Long, Long> { 
 
 private static final long serialVersionUID = 1L; 
 public static final Long ID = 0000L; 
 
 public IndustryICBCodeType() throws ProcessingException { 
   super(); 
 } 
 
 @Override 
 protected boolean getConfiguredIsHierarchy() { 
   return true; 
 } 
 
 @Override 
 protected String getConfiguredText() { 
       public Long getId() {


PIC

Figure 4.1: A hierarchical code type class shown in the Scout SDK.


The corresponding code for the ICB code type is provided in Listing 4.3 where its hierarchical nature is reflected by method getConfiguredIsHierarchy. The actual hierarchical codes are then implemented as nested inner code classes that are derived from Scout class AbstractCode. See Figure 4.1 for a screenshot of the partially expanded ICB code type class in the Scout SDK.

4.3.3 Loading Codes Dynamically

Although codes types remain mostly static in their nature, they do evolve over time in any real world application. Requiring that all codes are statically defined in the application’s code base would result in the necessity to update the code base for every change of a code required by the business. Clearly, such a setup is not sustainable and this is why Scout allows to dynamically update the set of codes contained in a code type.


Listing 4.4: Adding codes dynamically in method execLoadCodes.
 
import org.eclipse.scout.rt.shared.services.common.code.AbstractCodeType; 
import org.eclipse.scout.rt.shared.services.common.code.CodeRow; 
import org.eclipse.scout.rt.shared.services.common.code.ICodeRow; 
 
/** 
* @author mzi 
*/ 
public class ColorsCodeType extends AbstractCodeType<Long, Color> { 
 
 private static final long serialVersionUID = 1L; 
 public static final Long ID = 20000L; 
 
 public ColorsCodeType() throws ProcessingException { 
   super(); 
 } 
 
 @Override 
 protected String getConfiguredText() { 
   return TEXTS.get(Colors); 
 } 
 
 @Override 
 public Long getId() { 
   return ID; 
 } 
 
 @Override 
 protected List<? extends ICodeRow<Color>> execLoadCodes(Class<? extends ICodeRow<Color>> codeRowType) throws ProcessingException { 
   List<ICodeRow<Color>> codes = new ArrayList<ICodeRow<Color>>(); 
 
   codes.add(new CodeRow<Color>(Color.PINK, TEXTS.get(Pink))); 
   } 
 
   @Override 
   public Color getId() { 
    return ID; 
   } 
 } 
 
 @Order(120.0) 
 public static class YellowCode extends AbstractCode<Color> { 
   private static final long serialVersionUID = 1L; 
   public static final Color ID = Color.YELLOW; 
 
   @Override 
   protected String getConfiguredText() { 
    return TEXTS.get(Yellow); 
   }

At startup of a Scout application the codes of all defined code types are loaded into memory. For this, Scout internally calls method loadCodes for each code type class derived from class AbstractCodeType. In this method Scout first creates objects representing the statically defined codes and then dynamically adds additional codes in method execLoadCodes. By overriding this method, a code type class can dynamically add codes from any external sources. An example for the dynamic loading of codes is provided in Listing 4.4. Please note that this code snipped only illustrates the principle and does therefore not access any external web services or databases.

As codes have IDs and can be defined both statically in code and dynamically from external data, conflicting definitions of codes are inevitable. In the Scout framework these conflicts are resolved in method execOverrideCode. In the default implementation provided by class AbstractCodeType, priority is given to the dynamically defined code. Only attributes that are undefined for the dynamic code are copied from the static code definition. This logic can be changed for any code type by simply overriding method execOverrideCode with the desired behaviour. In the example provided in Listing 4.4 the code with ID Color.YELLOW is defined both statically and dynamically. As a result, the translated text for key "YellowDynamic" is shown in the user interface as it has priority over the statically defined text key "Yellow".

To have access to all codes at runtime, Scout provides the convenience accessor CODES. This accessor encapsulates the access to the ICodeService and provides a number of useful methods. At startup, all codes are loaded and cached in the applications client session using method getAllCodeTypes. And for a class MyCodeType, all its codes can be retrieved by CODES.getCodeType(MyCodeType.class).getCodes().

4.4 Lookup Calls and Services

Lookup calls are are used to look up lists of lookup rows in the form of key-text pairs. The list of lookup rows returned is usually defined by some search criteria. When the look up is triggered by a key, only a single element is returned. And when a string is provided as a search criteria, the returned list typically contains the lookup rows that contain the given search text as a substring.

For lookup calls two main use cases exist. In the first case, the lookup data is locally available, not too large and can be kept in memory. In this situation, the lookup data can be directly created in the call itself. As an example, you may consider a lookup call where the lookup data is based on a code type. In the other case, the lookup data is dynamic in nature, the amount of data is large and needs to be read from some external source, such as a database or a web service. To access large amounts of external data, a lookup call typically invokes a so called lookup service that is providing the necessary data. This is exactly the scenario that was used in the ”My Contacts application of the book’s first part in Section ??. In the contact form of that application, a company smart field is used to let the user select a specific entry from a list of companies. And in turn, this smart field uses a company lookup call that is backed by a company lookup service. This lookup service then accesses a database to create the list of companies required for the company smart field.

in the text below (0) general aspects: * getDataByKey—Text—Rec?—All * additional properties as constraints to the result set: master field * for a specific implementation additional properties can be added with getters/setters ? -¿ yes as they are passed to services as bind variables (1) local lookup calls in the client plugin (2) lookup calls in the shared plugin (3) lookup services are only mentioned here for completeness. full discussion in book part 3 for scout server? or not? probably needs to be here ...


Listing 4.5: A simple local lookup call defining it’s entries in method execCreateLookupRows.
 
import org.eclipse.scout.rt.shared.TEXTS; 
import org.eclipse.scout.rt.shared.services.lookup.LocalLookupCall; 
import org.eclipse.scout.rt.shared.services.lookup.LookupRow; 
 
/** 
* @author mzi 
*/ 
public class FontStyleLookupCall extends LocalLookupCall<Integer> { 
 
 private static final long serialVersionUID = 1L; 
 
 @Override 
 protected List<LookupRow<Integer>> execCreateLookupRows() throws ProcessingException { 
   ArrayList<LookupRow<Integer>> rows = new ArrayList<LookupRow<Integer>>();


Listing 4.6: A local code lookup call. This lookup removes inactive codes in the lookup data.
 
 
import org.eclipse.scout.commons.exception.ProcessingException; 
import org.eclipse.scout.rt.shared.services.common.code.ICode; 
import org.eclipse.scout.rt.shared.services.lookup.CodeLookupCall; 
import org.eclipse.scout.rt.shared.services.lookup.ICodeLookupCallVisitor; 
import org.eclipse.scout.rt.shared.services.lookup.ILookupRow; 
import org.eclipsescout.demo.widgets.shared.services.code.EventTypeCodeType; 
 
/** 
* @author mzi 
*/ 
public class EventTypeLookupCall extends CodeLookupCall<Long> { 
 
 private static final long serialVersionUID = 1L; 
 
 @Override 
 protected List<? extends ILookupRow<Long>> execCreateLookupRows() throws ProcessingException { 
   //TODO [mzi] Auto-generated method stub. 
   return super.execCreateLookupRows(); 
 } 
 
 /** 
  * Visitor class that filters out inactive codes.

TODO: fix Figure 4.2: MyLookupService extends AbstractLookupService and implements IMyLookupService that extends ILookupService which


PIC

Figure 4.2: Implementing a lookup call with a corresponding lookup service. Scout framework components are shown in orange, user code in blue.


Existing Documentation

* lookup service * sqllookup service

4.5 Permissions

needs text, topic is relevant for client, server, and security. what to present where to be decided

Existing Documentation

4.6 Form Data Objects

needs text, explain that form data objects are data transfer objects

Existing Documentation

4.6.1 Data Binding

needs text, this is about Form Data Export and Import

4.6.2 Automatic Updates by the Scout SDK

needs text

4.6.3 Manual Form Data Updates

needs text