02 DLM Administration Guide

Distributed Layout Management (DLM)

Contents

What is DLM and where did it come from?
Configuring_uPortal_to_Use_DLM
DLM_Guest_Fragment
Introducing_dlm.xml
Defining_Fragments
Defining_Audiences
Setting_up_Fragment_Layouts
Custom_UI_Changes
Future_Direction

additional guidances and best practices

What is DLM and where did it come from?

In uPortal, Layout Management refers to how the user interface seen by a user is generated and changed. In version 2.0, only Simple Layout Management, SLM, was available in the portal. All layout pieces like tabs, columns, and channels were owned by the user. There was little control available for an institution to control a user's layout. When Sungard SCT, then Campus Pipeline, adopted uPortal for their Luminis product they had to allow schools to choose how much or how little of the layout is locked in place. Furthermore, this should be modifiable at any time and such changes should then appear in the portal. The result was Distributed Layout Management or DLM which debuted in Luminis in 2002. 

This resulted in JA-SIG designing a similar feature known as Aggregated Layout Management or ALM. With the advent of ALM there were two approaches to dynamic layout management. However, although they have complimentary features, ALM and DLM each provide benefits that are not had by the other implementation. In 2004 Sungard SCT was contacted to see if the features of ALM and DLM could converge into a single offering. The benefits are obvious. With the community working to enhance the features of a single offering all will benefit. Accordingly, work was started in late 2004 to contribute DLM back to the community and have it available starting in uPortal version 2.5.0.

Configuring uPortal to Use DLM

uPortal version 2.5 comes configured to use ALM by default. To convert between the different layout management approaches follow these simple steps.

Step 1: Stop the web server if not stopped already.

Step 2: Open portal.properties and search for any of these three accronyms. There are two properties that the portal uses to startup the appropriate code to perform that layout management functionality. Preceding each of these properties is a comment block outlining what value that property should have for each of the respective layout management approaches. The properties that need to be changed are:

portal.properties to be Changed

org.jasig.portal.layout.UserLayoutStoreFactory.implementation

org.jasig.portal.layout.UserLayoutManagerFactory.coreImplementation

After changing this value redeploy using, "ant deploy", so that the modified portal.properties file is pushed to <webApplicationRoot>/WEB-INF/classes/properties unless you changed the version in that location.

Step 3: Modify user accounts in the database. Specifically, the UP_USER_PROFILE table contains a lookup of the structure and theme stylesheets that should be used by users. The following SQL can be used to modify the values for the respective layout management approaches. See the following table for the specific stylesheet values that come in the default uPortal database.

UPDATE up_user_profile
SET structure_ss_id=<struct Id From Below>,
theme_ss_id=<theme Id From Below>
WHERE theme_ss_id=<current Theme Id In up_user_profile>

Approach

Structure Stylesheet Id

Theme Stylesheet Id

SLM

1

1

ALM

3

11

DLM

4

3

Step 4: Restart the web server.

DLM Guest Fragment

When you first configure the portal to use DLM, start up the web server, and go to the portal with a browser you will notice a new "Welcome" tab appears. Of the tabs in the login page, this one is unique. Most are part of the guest user's own layout. This tab isn't. In DLM terminology it is a fragment that was merged in by DLM. Traditionally, if you wanted to change what guests see you would set a password for the guest user, log in as guest, and change the layout. Not with DLM. To change the contents of this tab log in with the following user id and password:

User Id: guest-lo, Password: guest-lo

This user is a DLM fragment owner. This account has all of the same capabilities as a regular user with one exception, no fragments are merged into a fragment owner's layout. Fragment owners see only their owned layout since that layout becomes the fragment that is pushed into other layouts.

Now once you log in, change the guest fragment, and log out, you will notice that this tab didn't change. Doesn't DLM push changes to the guest layout? Of course it does. The problem here is that the guest layout that you see is cached in a layout manager. For regular users a layout manager is loaded when they log in. Hence, so is their layout. The guest layout manager is loaded when the first request is made to the portal after starting up and is cached in memory thereafter. So changes made to fragments that go to regular users will present their changes the next time that a user logs in after that fragment has been changed. But currently, to see changes pushed to the guest layout, the portal must be restarted. This will be fixed soon. We hope.

Introducing dlm.xml

When DLM was developed, time was of the essence. A new user interface taylored to building fragments and a new database schema was too aggresive an undertaking for engineers new to the uPortal code base. Upon further investigation of the portal architecture and database schema it was determined that a derivative approach could be taken instead. In a derivative approach, existing, reliable pieces of the portal could be used to produce layout fragments to be pushed to users. Furthermore, there would be no database schema changes. Specifically, fragments would be obtained by using regular portal accounts to define what each fragment should look like. Such was and is the design of DLM. A configuration file, dlm.xml defines fragments, their audiences, and the special portal accounts used to set up their layouts. (See Future Direction on how dlm.xml will be replaced in the near future.)

Although dlm.xml is xml based it does not have a defined schema or DTD. Its expected structure is defined by the expectations of the DLM loading infrastructure. This is in part due to the extensible nature of dlm.xml as will be seen in the declarations of the fragment audience definitions. Therefore, the remaining information in this section and related sections will portray the implicit structure expected by the DLM loading infrastructure.

The dlm.xml file is located in the properties directory. The top level element in dlm.xml is the <managedLayoutFragments> element. It includes the namespace declaration for DLM used to prefix all expected DLM property, fragment, and audience elements. This element appears as follows in dlm.xml.<managedLayoutFragments xmlns:dlm="http://org.jasig.portal.layout.dlm.config">
The only two supported child elements for managedLayoutFragments are <dlm:property> and <dlm:fragment>. Others may be included but they will be ignored. The <dlm:property> element has two required attributes, 'name' and 'value'. There are currently only two properties supported by DLM and if not defined, suitable defaults will be used as explained below.

The 'defaultLayoutOwner' Property

If defined the value of this property should be the user ID (ie: the log-in ID) of an account whose layout should be copied for all new fragment owners. When a fragment is defined in dlm.xml it includes an ownerID attribute. (See the related section on defining fragments.) Since fragments are layouts for special accounts then these accounts must have a layout. When regular users log in for the first time and have no layout, the portal gives them a copy of a default account's layout as declared in portal.properties. This default should not be used for fragment owner accounts since it will result in that entire layout being pushed to all users. The approach take by the default dlm.xml is to use a special account included in the portal. To change this account you can use the following credentials.

User Id: fragmentTemplate, Password: fragmentTemplate

Warning: It is strongly recommended that you do not change this user account's layout. It is empty except for hidden content like the header and footer folders and their channels. The layout for this account including hidden but necessary content is copied whenever a new fragment owner is declared in dlm.xml. The layout for the owner account is created immediately after adding the fragment's declaration to dlm.xml and restarting the portal. These accounts should be empty until such time that the account can be accessed and the proper layout set up that should be pushed for that fragment.

The 'org.jasig.portal.layout.dlm.RDBMDistributedLayoutStore.fragment_cache_refresh' Property

For performance, DLM caches the layout for each defined fragment in memory. When layout owners modify the layout, those changes are pushed into the database and into the in-memory cache in the server handling the session for that account. If multiple servers are employed, the other servers will not see these changes made by the fragment owner. This property determines how often the cache of fragment layouts is reloaded to force such changes to appear in other servers. This does not include instantiating new fragments declared in dlm.xml. This only forces a reload of the fragments seen in dlm.xml when the servers were last restarted.

Defining Fragments

The <dlm:fragment> child element of the outer most managedLayoutFragments element is used to define a fragment. There is no restriction on the number of child <dlm:fragment> elements of managedLayoutFragments. The following sample is one of the fragments defined in the default dlm.xml file that comes with uPortal.

<dlm:fragment name='Guests' ownerID='guest-lo' precedence='10'>
  <dlm:audience evaluatorFactory='org.jasig.portal.layout.dlm.providers.GuestUserEvaluatorFactory'/>
</dlm:fragment>

All elements defined and expected by DLM are prefixed with dlm indicating that they are part of the DLM namespace. The fragment element has a name attribute that should be unique for all fragments. This name is presented in the title bar of the portal when the owner of this fragment is logged in as shown below.

The 'ownerID' Attribute

Each fragment must declare an ownerID attribute. This is the log-in to use when logging in to edit the layout for this fragment. It is important that this account not exist prior to adding the fragment. When dlm.xml is modfied, the portal must be restarted for the configuration to be loaded. Upon loading, if that account already exists and has a layout it will immediately be pushed to users. If the account does not exist, then upon restarting the portal, DLM will create that account and populate its layout with a copy of the layout of the account specified with dlm.xml's defaultLayoutOwner property. That layout has no visible content. In this way this fragment does not push any content to users until the owner has time to set up the layout that should be pushed. Note: the md5passwd command line utility must still be used after restarting to set the password for the new account to allow a fragment maintainer to log in to that account and set up the layout:

ant md5passwd -Dusername=guest-lo
The 'precedence' Attribute

Each fragment must also declare an integer precedence value. This value is used during merging of fragments to position elements contributed from different fragments. It is also used to determine that precedence elements can override a lower precedence, movement-restricted element forcing it to a less valueable real-estate location. For example, the default dlm.xml file defines three fragments:

Guests

precedence = 10

Entertainment

precedence = 100

News

precedence = 80

When a regular user, in this case the student account, logs in to the portal and selects the Preferences link the following ordering of tabs will appear. Note that the entertainment tab can move to the right of the news tab but that the student tab is not allowed to move to the left of the news tab.

This behavior is due to the owner of the news tab's fragment marking the news tab as not moveable. However, restricting movement is relative. All elements from a fragment inherit the precedence of that fragment. A tab from a fragment with higher precedence like the entertainment tab, can override a movement restriction of a lower precedence tab.

Now the student tab is owned by the student user. User layout elements have a precedence of zero and hence any fragment element can always force user owned elements to lower-valued real-estate locations. However, if a fragment element has not been movement restricted then lower precedence tabs can move them as is shown below with the student tab moved to the left of the entertainment tab. But note that due to the locked news tab and the relative precedences that the student tab is never allowed to move beyond the news tab.

As can be seen, movement restrictions restrict movement of lower precedence elements to higher valued screen real-estate locations. DLM allows users to alter fragment elements pushed into their layouts if such changes are allowed by the fragment. This means that users can add columns to fragment tabs and channels to fragment columns. Accordingly, real-estate value differs based on element type. For tabs, the most valued real-estate is furthest to the left since tabs to the right can ultimately be forced off of the right side of the page and outside the view being shown by the browser. Columns have a similar value direction of left to right from highest to lowest value for a similar reason. Channels have a direction from the top of a column to the bottom for highest to lowest value respectively since channels further down in a column can be forced off of the bottom of the browser's visible viewing area.

When multiple fragments have equal preference the order of appearance is determined by the order in DLM.xml.

Defining Audiences

Each <dlm:fragment> element can contain from zero to many <dlm:audience> elements. Each audience element defines a group of users who will receive that fragment. If a fragment has more than one audience element then the set of users that get that fragment is the union of all nested audience elements.

The 'evaluatorFactory' Attribute

The <dlm:audience> element has a single required attribute, evaluatorFactory. This attribute should have the fully qualified path name of a class which implements the org.jasig.portal.layout.dlm.EvaluatorFactory interface for aquiring an evaluator. The factory implementation should have a zero argument constructor and implement the only method in the interface:

public Evaluator getEvaluator( org.w3c.dom.Node audience )
throws Exception;

The DLM infrastructure will instantiate the factory using the zero argument constructor and call getEvalutator passing a node representing the <dlm:audience> element. This can then be used by the factory to return an evaluator appropriate for any configuration information included within the audience block. This means that the contents of the audience element are dictated completely by the declared EvaluatorFactory.

The object returned from getEvalutator must implement the org.jasig.portal.layout.dlm.Evaluator interface as shown below.

public boolean isApplicable( IPerson p )

DLM obtains from each audience's factory an evaluator and when a user logs in it passes through every fragment asking its audience evaluators, isApplicable, passing an IPerson implementation. If the user meets the requirements defined for that audience then the method returns a value of true and that fragment is included in the layout for that user. If the factory is unable to create and return an evaluator it should throw an Exception with a clear message indicating the problem. For example, suppose the element were as follows:

<dlm:audience evaluatorFactory="IPersonEvaluatorFactory"/>

This would result in the IPersonEvaluatorFactory, to be explained shortly, throwing an exception with the following message since it requires nested configuration content:

Invalid content. Expected one to many <paren>, <NOT>, or <attribute> in '<dlm:audience evaluatorFactory="IPersonEvaluatorFactory"/>'

If an exception is thrown when obtaining an evaluator from an evaluator factory then the message is logged as a warning and the audience element in question is discarded and not included in the evaluators for that layout fragment. Other evaluators for that layout would still be in effect.

The following evaluator factories are provided. All are found in the org.jasig.portal.layout.dlm.providers package.

The GuestUserEvaluatorFactory

This factory produces an evaluator that returns the value of IPerson.isGuest(). As such it does not use any configuration information within the audience element that declares it so the element can be empty. This factory is used in the version of dlm.xml included in the portal to push the Guest fragment to the guest user so that it shows on the log-in page.

<dlm:fragment name='Guests' ownerID='guest-lo' precedence='10'>
<dlm:audience evaluatorFactory='org.jasig.portal.layout.dlm.providers.GuestUserEvaluatorFactory'/>
</dlm:fragment>

The AllUsersEvaluatorFactory

This factory produces and evaluator that always returns true. This can be used to push a fragment to all portal users including the guest user. Like GuestUserEvaluatorFactory it requires no content within the audience element and hence the element can be empty.

The PersonEvaluatorFactory

This factory produces an evaluator configured as defined by required content nested within its declaring audience element. It supports a configuration syntax from which arbitrarily complex grants of the fragment can be made based on attributes found in the passed-in IPerson object. Specifically, it obtains attributes from the IPerson object using the getAttribute call. The following syntax elements are supported.<paren> ELEMENT

This element has one optional attribute "mode" which can contain one of three cast-sensitive values: OR, which is the default, AND, or NOT. OR causes the paren element to evaluate all contained tests and if any of them returns true then it too will return true. AND returns true only if all contained tests are true. NOT inverts any contained test. If more than one contained test is included then a logical OR operation is performed first and that result inverted. It should be noted that when PersonEvaluatorFactory factory is used it provides an implicit element into which all child elements of <dlm:audience> are placed. So if your configuration requires such a top level paren element you can just specify its children within the <dlm:audience> element.<attribute> ELEMENT

This element is used to specify which one of five available tests should be performed on an attribute in the passed-in IPerson object. The particular attribute to be tested is indicated in the required name attribute. The required mode attribute indicates the type of test and can be one of the following: exists, equals, contains, startsWith, and endsWith. The value to be compared is indicated by the value attribute. The value attribute is not required and indeed not used for the "exists" mode. Values for both mode and name are case sensitive.

The Entertainment fragment included in the default dlm.xml file in the portal uses this factory to push the entertainment fragment to all users that do not have a "username" attribute with a value of "guest".

<dlm:fragment name='Entertainment' ownerID='ent-lo' precedence='100'>
  <dlm:audience evaluatorFactory='org.jasig.portal.layout.dlm.providers.PersonEvaluatorFactory'>
    <paren mode="NOT">
      <attribute name="username" mode='equals' value='guest'/>
    </paren>
  </dlm:audience>
</dlm:fragment>
The GroupMembershipEvaluatorFactory

This factory returns an evaluator that can evaluate group memberships. Specifically, the returned class inherits from the evaluator provided by PersonEvaluatorFactory. This means that its syntax semantics are identical except for the <attribute> element. Its semantics are overwritten to support 2 modes (as of uP 2.5.1), memberOf and deepMemberOf. memberOf will test for membership of the named group only, whereas deepMemberOf will also test for membership in groups contained by the named group. The name attribute should contain the name of the group with matching case. The value attribute is not used. The News fragment in the default dlm.xml file in the portal uses this factory to push the news fragment to members of the Students group who are not also members of the Faculty group.

<dlm:fragment name='News' ownerID='news-lo' precedence='80'>
  <dlm:audience evaluatorFactory='org.jasig.portal.layout.dlm.providers.GroupMembershipEvaluatorFactory'>
    <paren mode="AND">
      <attribute mode='memberOf' name='Students'/>
      <paren mode="NOT">
        <attribute mode='memberOf' name='Faculty'/>
      </paren>
    </paren>
  </dlm:audience>
</dlm:fragment>

Note: dlm.xml was designed to allow institutions the ability to define and plug-in their own custom evaluators. The dlm.xml file will be replaced in the near future with the new permissions work that is targeted for uPortal 2.6.0. That solution will have more flexibility than is had with the current design of dlm.xml. For example, although completely different technology, logically the new solution blurs the boundary between audience elements allowing person attribute tests to be combined in the same boolean equation as group membership evaluations. When DLM migrates to that new approach only these classes and their semantics are guaranteed to be migrated. Any configuration added via custom factories from an institution will have to be planned for and migrated by that institution as part of upgrading to the version of DLM in 2.6.0.

Setting up Fragment Layouts

Once a fragment is defined in dlm.xml, the server bounced, and the password configured for the new fragment owner account, a fragment maintainer can log into that account and set up the layout that should be used for that fragment. For this, an extended version of SimpleLayoutManagement's Preferences channel is provided and is the channel seen when using DLM and the Preferences link is selected. For non-fragment users they see that channel in the traditional manner. For fragment owner the preferences channel changes slightly to indicate the name of the fragment that is being edited as can be seen in the images below. Additionally, controls are added to the user interface to provide the ability to restrict what users of the fragment can do to fragment elements.

Tabs

In the image below the typical controls for a tab are shown along with some DLM specific fragment-user-actions that can be restricted. By default all check boxes are selected and hence all actions are allowed by end users. As seen in the image, the "Useful News" tab in the News fragment's layout restricts movement by end users of the fragment. To modify any of these actions the appropriate checkbox should be checked or unchecked as needed and the "Set Actions" button pressed. Each of these actions that can be restricted for tabs is discussed below.

h5 Move Tab
If moving a tab is restricted by a fragment owner then users will not be able to move any of their personally-added tabs to the left of this tab. If any tabs exist in the user's layout that come from a fragment with lower precedence as declared in dlm.xml then the user will also be unable to move those tabs to the left of this tab. Tabs from a fragment with higher precedence can be moved by the end user to the left of this tab. If any of these lower precedence tabs or user-added tabs were moved to the left of this tab prior to it being marked as movement restricted then those tabs will be pushed to the right of this tab when the user next logs back in. To the end user the inability to move a lower precedence tab including those added by the user is depicted by the lack of the buttons allowing the user to move the tab to the left as seen in the image below.

Edit Properties

If editing tab properties is restricted by a fragment owner then users will not be able to rename that tab in their layout. If a user has previously renamed that tab and the fragment owner then marks the tab to prevent editing of properties then the next time that the user logs in that tab name change will be discarded and the name set by the fragment owner will reappear. When such a tab is restricted from editing the controls for renaming that tab are removed from the user's view when selecting that tab as shown in the image below. The "Real Entertainment" tab has editing of properties restricted as can be seen by the missing renaming elements when viewed by the student user.

Add Columns

If adding columns is restricted by a fragment owner then users will not be able to add columns to that tab in their layout. If a user has previously added columns to that tab and the fragment owner then marks the tab to prevent adding columns then the next time that the user logs in those user columns will be discarded. (There is currently no holding place to such discarded items. Such a holding place similar to the waste basket concept could be added if there was a pressing needed and a channel could be created to allow a user to restore those items to some other location in their layout.) When such a tab is restricted from adding columns the "Add Column" buttons are removed from the user's view when selecting that tab as shown in the image below. The "Useful News" tab has adding columns restricted as can be seen by the missing buttons in the spaces between and to the left and right of columns when viewed by the student user.

Delete Tab

If deleting the tab is restricted by a fragment owner then users will not be able to delete this tab from their layout. If a user has previously deleted this tab and the fragment owner then marks the tab to prevent deleting then the next time that the user logs in, that tab will reappear. When such a tab is restricted from being deleted the "Delete this tab" link is removed from the user interface for that tab when end users are editing their layout.

Columns

The action-restricting controls for columns are nearly identical to those of tabs as is their application.

Move Column

If moving a column is restricted by a fragment owner then users will not be able to move any columns that they have added to the tab to the left of this column assuming that the tab allowed them to add their own columns. If any user-added columns have were previously added to the left of this column and the fragment owner marked this column as movement restricted then those user added columns will be bumped to the right of this column the next time that the user logs in. Additionally, the buttons for moving those user added columns to the left of this column are removed from the user interface when a user is editing that tab in their layout.

Edit Properties

Restriction of column property editing is identical to restriction of tab property editing except that the only property that currently exists for columns is width. If editing column properties is restricted by a fragment owner then users will not be able to change the column's width. They can read it but they can't change it as shown in the image below. Note that only one of these columns is marked as being edit restricted.

Add Channels

If adding channels is restricted by a fragment owner then users will not be able to add channels to that column in their layout. If a user had previously added channels to that column and the fragment owner then marked the column to prevent adding channels then the next time that the user logs in those user added channels will be discarded. When such a column is restricted from adding channels, all "Add Channel" buttons are removed from the user's view of that column.

Delete Column

If deleting the column is restricted by a fragment owner then users will not be able to delete this column from their layout. Additionally, the user will not be able to delete the tab containing this column. When such a column is restricted from being deleted the "Delete this column" link is removed from the user interface for that column and the "Delete this tab" link is removed for its containing tab when end users are editing their layout.

Channels

The action-restricting controls for channels vary from those of columns and tabs in that only move and delete are restricted.

Move Channel

If moving a channel is restricted by a fragment owner then users will not be able to move any channels that they have added above this channel assuming that the column allowed them to add their own channels. If any channels were previously added above this channel and the fragment owner marked this channel as movement restricted then those user added channels will be bumped below this channel the next time that the user logs in. Additionally, the buttons for moving those user added channels above this channel are removed from the user interface when a user is editing the column containing that channel in their layout.

Delete Channel

If deleting a channel is restricted by a fragment owner then users will not be able to delete that channel from their layout. Additionally, the user will not be able to delete the containing column and tab. If any of these were previously removed by the user and the fragment owner then marked that channel as undeletable then the tab and all of its columns and channels would reappear the next time that the user logged in. When such a channel is restricted from being deleted the delete button for the channel is removed from the user interface when an end user is editing their layout. Additionally, the "Delete this column" link is removed from the user interface for that channel's containing column and the "Delete this tab" link is removed for its containing tab.

Custom UI Changes

As enhancements are worked on for DLM like Integrated Modes support there is often a need to add server side code to handle specific URL parameters to fulfill some function. Within layout managers in general the place where such code is typically placed is within the layout manager's
processLayoutparameters() method. Often, such changes are unique to the specific structure transformation that is in use. But within layout managers and the uPortal code in general there is no knowledge of specific structure transformation concepts like tabs and columns. The infrastructure knows only about folder objects containing other folder objects, to any depth, and leaf node objects known as channels. A structure transformation then takes this generic hierarchy and transforms it into its desired representation such as all top level folders being interpreted as tabs with the next level interpreted as columns containing a nested set of channels.

This internal model of hierarchical folders was done intentionally in the design of uPortal so that it could potentially be used with whatever structure was desired that could map into this underlying, flexible model. Hence code placed within org.jasig.portal.layout.dlm.DistributedLayoutManager's processLayoutparameters() method must accomodate this underlying model often making code much more complex than it otherwise would be if structural transformation concepts could be taken into consideration. Furthermore, such custom changes usually don't make sense to contributed back to the uPortal baseline code and hence will have to be added back in and recompiled each time that the portal is upgraded to the latest
version of the uPortal code.

Parameter Processing Pipe

Starting in uPortal 2.6 a configuration based, pluggable mechanism is available in DLM allowing an institution to plug in handlers that can act on query and post parameters included in an HTTP request. These handlers can also take part in altering the SAX event stream that represents the user's layout including adding, removing, or altering layout elements without affecting their canonical structure within the DistributedLayoutManager. This pluggable handler support is provided via what is known as the Parameter Processing Pipe. Conceptually, the location of the pipe is shown in the image below.

The uPortal user interface is generated by the class org.jasig.portal.UserInstance. As part of that processing UserInstance delegates to the plugged-in LayoutManager for processing layout parameters. Then it again delegates to have the layout pushed through UserInstance's rendering mechanism as a stream of SAX events. This event stream is what drives the structure and theme transformation. Both interactions pass through the Parameter Processing Pipe. Although shown in the image as being between UserInstance and DistributedLayoutManager the pipe is actually internal
to DistributedLayoutManager and is delegated to by the processLayoutParameters() and getUserLayout() methods.

Processor Interfaces

Plugging a handler in is accomplished by implementing at least one of two new interfaces as shown in the next figure. IParameterProcessor implementations can take part in the processLayoutParameters() call. ISaxProcessor implementations can take part in modifications to the SAX event stream. If a processor implements both interfaces then it can take part in both actions. Both processor types can be plugged-in as part of a set of fixed processors. This means that they are always there and always take part in every invocation of these calls.

Alternatively, processors can be included in a Map of optional processors with each processor being registered with a key that is unique among all registered optional processors. A single optional processor can be installed into the pipe and take part in both of these invocations until another HTTP request selects a different optional processor or removes the current optional processor. Alternatively, if an optional processor implements the IOptionalProcessor
interface then it can cause itself to be removed from being the currently selected optional processor when it has completed its processLayoutParameter tasks.

Optional Processor Selection

An optional processor is selected in an HTTP request by specifying a query or posted parameter of uP_dlmPrc=someKey. The key specified should match one of the registered optional processors. When such a parameter is seen the Parameter Processing Pipe installs that optional processor prior to handling the processLayoutParameters request. At the end of processing layout parameters
by delegating to processors the Pipe checks to see if the current optional processor implements the IOptionalProcessor interface. If it does and the processor indicates by the single method of that interface that it is finished then it is removed from being the currently
selected optional processor. Such a check is made each time that processLayoutParameters() is called.

If that processor does not implement the IOptionalProcessor interface then it will remain as the currently selected optional processor until another HTTP request includes another uP_dlmPrc
parameter. If the value of that parameter is an empty String then the optional processor is removed. If it contains another key then the new processor becomes the optional processor. However, it should be noted that these processor instances are not garbage collected. They remain cached in memory until the next time that processor is needed.

Plugging in Processors

The Parameter Processing Pipe is configured by modifying the properties/dlmContext.xml file. This file has the following structure. In the default configuration two fixed processors are included. Both processors, the ThemeParamInjector and RegularViewChannelRemover implement IParameterProcessor. The former acquires the user's name via IPeron's getFullName() method and injects it into the theme stylesheet as the userName parameter. The latter handes the requests that result when the delete button is pressed on a channel when viewing the portal in regular non-layout-editing mode.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id='dlmProcessingPipe'
        class="org.jasig.portal.layout.dlm.processing.ProcessingPipe"
        singleton="false">

        <property name="fixedProcessors">
            <list>
                <bean class="org.jasig.portal.layout.dlm.providers.ThemeParamInjector"
                    singleton="false"/>
                <bean class="org.jasig.portal.layout.dlm.providers.RegularViewChannelRemover"
                    singleton="false"/>

                <bean class="some.other.processor.class.name" singleton="false"/>

                ... additional fixed processors

            </list>
        </property>
        <property name="optionalProcessors">
            <map>
                <entry key="some.String">
                    <bean class="another.processor.class.name" singleton="false"/>
                </entry>

                ... additional entries

            </map>
        </property>
    </bean>
</beans>

Fixed processors are added by inserting additional bean declarations as shown within the fixedProcessors list. On each bean declaration the class of the processor is specified as the value of the class attribute. Optional processors are added to the optionalProcessors map in a similar fashion by adding entries with the key attribute of the entry being the key for that processor and the class attribute of the nested bean element containing the class of the processor.

The value of the singleton attribute must be specified with care. A Parameter Processing Pipe is instantiated for each user and remains for the duration of that user's session. The specified set of processors are also instantiated. If a processor is thread safe meaning it does not contain any user specific information stored in instance variables then a single instance of that processor could be used in all pipes for all users. To do so the singleton attribute should be set
to true. If the processor is not thread safe and maintains user or state information then its singleton attribute should contain a value of false.

Sample Processors

There are two sample processors included with the Parameter Processing Pipe implementation code that can be plugged in to portray the flexibility and power had by processors. These sample processors are found in the following two classes.

org.jasig.portal.layout.dlm.processing.ExampleBookmarksRemover
org.jasig.portal.layout.dlm.processing.ExampleStickyTabEnforcer

The first sample processor is the ExampleBookmarksRemover. It implements the ISaxProcessor interface. When in place either as a fixed processor or as the currently selected optional processor it watches for SAX events for a channel with a name of Bookmarks. All such events are stripped from the SAX event stream and log entries are made of such activity. The result is that
any instances of the Bookmarks channel do not appear anywhere in the portal's user interface although the channel is still included in the layout. In a similar fashion whole new groups of elements can be injected into the event stream to incorporate layout that is not part of the internal layout built of user persisted elements and fragments.

The target elements used in the Integrated Modes approach with other layout managers is an example. Such target elements typically containing attributes like parentID and nextID and are injected between regular layout elements. When these elements are seen by the theme stylesheet they are used to add icons showing where new elements like channels can be inserted or where a selected element can be moved. A suitable processor could then be targeted as part of the link for icons allowing the appropriate actions to be taken in DistributedLayoutManager.

Alternatively, a processor could dynamically add attributes like up, down, left, or right to each channel, column, or tab as applicable to portray in what direction a particular element can be moved by the user. And again, the theme stylesheet could provide suitable icons to
portray that ability and the URL to hit to accomplish that move.

The second sample processor is the ExampleStickyTabEnforcer. It implements the IParameterProcessor interface and watches for a folder with a name of Sticky Tab. When in place either as a fixed processor or as the currently selected optional processor it watches for a folder with a name of Sticky Tab. If seen then it injects the ID of that tab into the structure stylesheet as the value of the activeTab parameter. The effect is that the Sticky Tab will be the selected tab and no other tab can be selected. Such an approach could be used to force a specific tab to maintain focus until some link is selected by the user that could delegate to another processor causing the sticky tab functionality to be removed.

There are many possible layout management approaches and features that could be provided by suitable URL handling processor sets and the related structure and theme transformation stylesheets. The pipeline's pluggability allows for all of these tightly coupled, collaborating pieces to be developed in a modular fashion and added in as desired. For example, these groupings could be treated as separate DLM UI projects in the repository. Then based on the features offered by a set, institutions could elect to drop that set into their version of the portal, register those stylesheets, and change user accounts to use those stylesheets.

Future Direction

The initial release of DLM in uPortal 2.5.0 was the version of DLM released in all Sungard SCT Luminis product versions released from 2002 through 2006. This is referred to as DLM 1.0. Luminis IV released in 2007 and incorporated many new features including the parameter pipeline, a Fragment Manager channel that replaces dlm.xml, subscribe-able fragments and a channel to manage subscriptions, and support for delegation of fragment administrative tasks. This version of DLM is referred to as DLM 2.0. Although the processor pipe feature is included in uPortal 2.6.0, more work is needed to roll the remaining new features from the snapshot repository area into the 2.x baseline to bring it fully up to the DLM 2.0 level. If you have suggestions or questions on these items or would like to assist in that effort please share you thought on the uPortal email lists.

Fragment Manager

In DLM 2.0 dlm.xml file is no longer used. It is replaced with the Fragment Manager channel as seen running in Luminis IV in the image below. The set of configured fragments is persisted in the uPortal database. The uPortal entity cache is used to convey to other servers in a cluster that fragments have changed and should be loaded. Such changes include not only fragment definition changes but also fragment layout changes and published channel changes where such channels are found in the layouts of one or more fragments. Most items currently configured using the dlm.xml file are visible. For example, precedence is clearly indicated by order in the list. Fragments at the top have highest precedence. The arrow buttons allow for increasing or decreasing precedence in a very straightforward manner. A new feature in DLM 2.0 is depicted by the green lamp indicator next to most of the fragments. Each fragment can be enabled or disabled at any time. Such functionality was only possible in DLM 1.0 by removing the definition from dlm.xml.

The name of each fragment corresponds to the "name" attribute of the <dlm:fragment> element. The delete button is for deleting a fragment. The edit button immediately to the left of the delete button allows an administrator to change the name and type of the fragment. Note that both pushed and subscribed fragments appear in the same view in the Fragment Manager. This is important since each type can restrict movement of tabs and hence those tabs may be competing for location in a user's layout. The ordering here with respect to each other clearly shows which will have greater precedence when competing in a user's layout.

The audience selected for each fragment is shown to the right the fragment. Note the complex boolean expressions based on both user attributes and group membership constructs. The exhibited expressions were created from a special Permissions Management infrastructure that is not slated to be contributed back to the uPortal codebase. So some work is needed to exchange that for support of the evaluation factories from DLM 1.0. Such functionality will then provide a straightforward migration path for DLM 1.0 installations to the DLM 2.0 version.

Miscellaneous

Attached to this page is a tool that can be useful for developers who are enhancing DLM or the uPortal user interface in general. DLM adds specific attributes to various pieces of a user's layout to keep track of certain characteristics: is this element part of a fragment, what is the fragment's precedence, what restrictions have been placed on this element, and so on. Additionally, when a user's layout is persisted only their owned portions and any changes to fragment elements are persisted. Changes to fragments are persisted via custom DLM elements in the layout known as directives. Hence the user's layout as viewed in the portal is a result of merging their personal or persisted layout fragment or PLF with the fragments that are to be integrated when they log in. As such the viewed layout is known as the incorporated or integrated layout fragment or ILF.

Both the ILF and the PLF can be viewed using a custom channel attached to this page. Download the dlmTools.jar to your machine and unzip it into the uPortal development directory. It will place files in source/org/jasig/uportal/layout/dlm/channels/tools. Then run "ant compile deploy" to have the LayoutExpose channel deployed into your uPortal installation. The channel does not support edit, help, or about and is a custom java channel with a class of "org.jasig.portal.layout.dlm.channels.tools.LayoutExpose". Once published and subscribed it provides links to view the PLF, ILF, ILF with structure stylesheet attributes injected, and the ILF with the structure transformation applied.

mrb 6/16/2007