Thursday Jan 10, 2013

Adding browser search engines in WebCenter Content

In a post I made a few years ago, I described how you can add WebCenter Content (UCM at the time) search to the browser's search engines.  I think this is a handy shortcut if you find yourself performing searches often enough in WCC. 

Well, in the PS5 release, this was actually included as a new feature.  You need to enable the DesktopIntegrationSuite component in order to access it.  Once you do, go to the My Content Server -> My Downloads link.  There you will see the 'Add browser search' link. 

Add Browser Search

Once clicked, an OpenSearchDescription XML file is produced which each modern browser supports for adding in the search engine. 

Browser Search Bar

The one piece that's missing is something I mentioned in my earlier post: forcing authentication.  If you haven't logged into the server, your search will be performed anonymously and you will only get back content that is available to the guest role.  To make sure the search is performed as your user, the extra parameter Auth=Internet can be passed to the server to cause the server to challenge your request and force a login if needed.  Because the definition of the search engine URL is defined within the DesktopIntegrationSuite component, a new custom component can be added to override this.  Basically, the new component must override the dis_search_plugin resource and modify the Url locations.  Below is an example:

<@dynamichtml dis_search_plugin@>
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns=""
    <ShortName><$if DIS_SearchPluginTitle$><$DIS_SearchPluginTitle$><$else$>Oracle WebCenter Content Server Search<$endif$></ShortName>
    <Url type="text/html" method="get" template="<$xml(HttpBrowserFullCgiPath & "?IdcService=DESKTOP_BROWSER_SEARCH&Auth=Internet&MiniSearchText={searchTerms}")$>" />
    <$iconlocation=strReplace(HttpBrowserFullCgiPath,HttpCgiPath,"") & HttpImagesRoot & "desktopintegrationsuite/dis_search_plugin.ico"$>
    <Image height="16" width="16" type="image/x-icon"><$iconlocation$></Image>
    <Developer>Oracle Corporation</Developer>
    <moz:SearchForm><$xml(HttpBrowserFullCgiPath & "?IdcService=DESKTOP_BROWSER_SEARCH&Auth=Internet&MiniSearchText=")$></moz:SearchForm>
<$setHttpHeader("Content-Disposition","inline; filename=search_plugin.xml")$>
<$setHttpHeader("Cache-Control", "public")$>

I've included a pre-built custom component that does just that.

UPDATE (Jan 15, 2013)

In addition to enabling the component, there is also a configuration preference that must be enabled.   After enabling the Desktop Integration Suite component,  go to the 'advanced component manager'.  Go to the bottom to the 'Update Component Configuration' list and select DesktopIntegrationSuite and click Update.  The first entry is to 'Enable web browser search plug-in'.  Check that and click Update.

DIS Configuration

If you've already restarted to enable the DIS component, you do not need to restart for this configuration to take effect.

Friday Oct 05, 2012

HTML Manifest for Content Folios

I recently worked on a project to create a custom content folio renderer in WebCenter Content. It needed to output the native files in the folio along with a manifest file in HTML format which would list the contents of the folio along with any designated metadata and a relative link to the file within the download.  This way a person could hand someone the folio download and it would be a self-contained package with all of the content and a single file to display the information on the contents.  The default Zip rendition of the folio will output the web-viewable version of the file with an HDA formatted file for each one. And unless you are fluent in HDA or have a tool to read them, they are difficult to consume.

Content Folio Manifest

I thought this might be useful for others, so I'm posting a copy of the component here. Beyond the standard instructions for installing a component, there is an environment configuration file (folionativezipwithmanifestrenderer_environment.cfg) which has a couple of options.

FolioMetadataManifestList - This is a comma separated list of metadata fields (system or custom) that should be included in the manifest file.

FolioMetadataManifestUseOriginalFilename - (True or False) If set to True, the filenames in the zip file will be based on the original filename as it was checked into WebCenter Content.  If False, it will use the 'Name' of the item as defined within the Folio.  This is usually the Title of the item.

The component also includes the source code, so feel free to use this as a reference for creating other interesting folios. 

Tuesday Jul 10, 2012

Adjusting the Score on Oracle Text search results

When you sort the results of a search by Score using OracleTextSearch as the search engine in WebCenter Content, the results coming back are based on the relevancy on the document.  In theory, the more relevant the search term is to the document, the higher ranked Score it should receive.  But in practice, the relevancy score can seem somewhat of a mystery.  It's not entirely clear how it ranks the importance of some documents over others based on the search term.  And often times, once a word appears a certain number of times within a document, the Score simply maxes out at 100 and the top results can be difficult to discern from one another.  Take for example the search for 'vacation' on this set of documents:

Score by relevance

Out of 7 results, 6 of them have a Score of '100' which means they are basically ranked the same.  This doesn't make the sort by Score very meaningful.  

Besides sorting by relevance, you can also tell Oracle Text to sort by occurrence.  In that case, it is a much more predictable result in how they would be ranked. And for many cases provide a more meaningful sorting of results then relevance. To change this takes a small component change to the SearchOperatorMap resource.  By default, the query used for full-text searching looks like:

<td>DEFINESCORE((%V), RELEVANCE * .1)</td>

Overriding this resource and changing it to:

<td>DEFINESCORE((%V), OCCURRENCE * .01)</td> 

will force it to now use occurrence (note the change in scale to .01 as well).  So running the same search and sort options as the example above, the results come out quite a bit differently:

Sort by occurrence

In this case, there is a clear understanding of how the items rank.   And generally, if the search term appears 3 times more in one document then another, it's got a better chance of being a document I'm interested in. 

You may or may not feel the relevance ranking is better then the search term occurrence, but this provides the opportunity to try an alternate method that might work better for your results.  A pre-built component is available for download here.

There is one caveat in using this method.  The occurrence ranking also maxes out at 100, so if a search term is in the document more then that, the Score result will stay at 100.

Thursday Mar 29, 2012

Crawling a Content Folio

Content Folios in WebCenter Content allow you to assemble, track, and access a logical group of documents and/or links.  It allows you to manage them as just a list of items (simple folio) or organized as a hierarchy (advanced folio).  The built-in UI in content server allows you to work with these folios, but publishing them or consuming them externally can be a bit of a challenge.  

The folios themselves are actually XML files that contain the structure, attributes, and pointers to the content items.  So to publish this somewhere, such as a Site Studio page, you could perhaps use an XML parser to traverse the structure and create your output.  But XML parsers are not always the easiest or most efficient to use. 

In order to more easily crawl and consume a Content Folio, Ed Bryant - Principal Sales Consultant, wrote a component to do just that.  His component adds a service which does all the work for you and returns the folio structure as a simple resultset.  So consuming and publishing that folio on a Site Studio page or in your portal using RIDC is a breeze! 

For example, let's take an advanced Content Folio example like this:

Folio view

If we look at the native file, the XML looks like this:

Folio xml

But if we access the folio using the new service - http://server/cs/idcplg?IdcService=FOLIO_CRAWL&dDocName=ecm008003&IsPageDebug=1 - this is what the result set looks like (using the IsPageDebug parameter).

Folio result set

Given this as the result set, it makes it very easy to consume and repurpose that folio.

You can download a copy of the sample component here. Special thanks to Ed for letting me share this component!

Monday May 23, 2011

Customizing Layouts and Skins in UCM 11g

custom skin

Along the same lines as my previous post on modifying the navigation menus, I thought I would cover how to customize layouts and skins in 11g.  Back in 10g, I had posted an entry on using configuration flags to continue to use the method of copying skins and layout directories under /weblayout to customize them.  I also mentioned that this method was going away in favor of using custom components to do the customizations.  Well in 11g, that is the only method. 

The technique is similar to what the 10g custom component would look like, but does include a few changes including some new approaches of using dynamicdata tables to drive data. 

To add new layouts, they get merged in the LmLayouts table.  New skins get merged into the LmLayoutSkinPairs table.  And the PublishedWeblayoutFiles and PublishedStaticFiles merged tables define what files get published to the weblayout directory.   Let's take a look at each.

In the following table, we're defining our new layout with an id, label, and marking it enabled. This is what will get merged into LmLayouts.

<@table CreateLayoutAndSkin_Layouts@>
<td>id</td> <td>label</td> <td>enabled</td> </tr>
<td>NewTopMenus</td> <td>New Top Menus</td> <td>1</td> </tr>

Next we'll define out to render the new layouts. This helps determine how the layout.js file is deployed dynamically. If you wanted to define a whole new layout altogether, you'd create a new layoutMode. This definition uses the new dynamicdata data table construct.

<@dynamicdata LayoutRenderModes@>
layoutName, layoutMode
NewTopMenus, Top Menus
NewTrays, Trays

In the next table, we'll define the skins to use for our new layout. We can also define an entirely new skin and apply it to either the new or existing layouts.

<@table CreateLayoutAndSkin_LayoutSkinPairs@>
<td>Top Menus</td><td>Gray</td><td></td><td>1</td>

The publishing of weblayout files happens in two ways. The first is the dynamic building and publishing of files. This is done for the layout JavaScript and skin CSS files.  In the case of the layout, it will use the TOP_MENUS_LAYOUT_JS template and for the skin, it will use the IDC_SKIN_CSS template.

<@table CreateLayoutAndSkin_PublishedWeblayoutFiles@>
<td>resources/layouts/NewTopMenus/layout.js</td> <td>TOP_MENUS_LAYOUT_JS</td> <td>javascript:layout:NewTopMenus</td> <td>50</td> <td><$if isLayoutEnabled("NewTopMenus") and (not DisableNewTopMenusPublishing)$><$doPublish = 1$><$endif$></td>
<td>resources/layouts/NewTopMenus/Oracle/skin.css</td> <td>IDC_SKIN_CSS</td> <td>css:layout:NewTopMenus</td> <td>50</td> <td><$if isLayoutEnabled("NewTopMenus") and (not DisableOracleSkinPublishing) and (not DisableNewTopMenusPublishing)$><$doPublish = 1$><$endif$><$tags="top_menus:oracle"$></td>

The second type of publishing is that of the static files such as images.

<@table CreateLayoutAndSkin_PublishedStaticFiles@>
<table border=1>
<td>publish/resources/layouts/NewTrays/Oracle</td><td>resources/layouts/NewTrays/Oracle</td><td>resources:layout:NewTrays</td><td>50</td> <td><$if isLayoutEnabled("NewTrays") and (not DisableOracleSkinPublishing) and (not DisableNewTraysPublishing)$><$doPublish = 1$><$endif$></td><td>0</td>

Many of the styles that get dynamically build with the skin.css file can be changed using the dynamicdata constructs.  For example, to change the link colors when in a trays layout:

<@dynamicdata css_vars_trays_oracle@>
name, value
linkColor1, #FF0000
linkColor2, #FF0000

These examples are rolled up into the sample CreateLayoutAndSkin component. It uses all the above techniques to create a new trays layout and top menus layout as well as a new skin. In the skin example, rather then creating a custom template and resources for the css file, a static one is defined within the static folders that gets published. Since it is custom, it's less likely that the css file needs to be dynamically built.

Hopefully this gets you on your way to customizing the UCM (or URM) UI for your own look & feel.

Wednesday May 11, 2011

Modifying Navigation Menus in UCM 11g

UCM Custom Navigation Menus

In UCM 11g, the way the navigation menus are constructed are done differently now.  In the past, this was handled with a navbuilder API in Javascript that allowed for menu choices to be manipulated with commands such as:

navBuilder.addChildNodeTo('ADMINISTRATION', 'item', 'id==FUNCTIONA', 'label==Function A'), 'url=='+httpCgiPath+'?IdcService=FUNCTIONA');

Well, in 11g that method has been deprecated in favor of a new method.   This new method takes advantage of a new data table construct in 11g Idoc Script called Dynamic Data Tables.  These allow you to create tables of data in Idoc Script and dynamically change them as opposed to the static table definitions.  This is useful for data that changes frequently and may be user the navigation menu.  I won't go into detail on Dynamic Data Tables here, but you can read up more about them in the Oracle Fusion Middleware Developer's Guide for Oracle Universal Content Management 11g Release 1 (11.1.1)

So for the example above, the code would now look like this in the custom component's resource file:

<@dynamicdata CoreMenuItems@>
id, label, linkType, linkData
FUNCTIONA, Function A, cgi, IdcService=FUNCTIONA

<@dynamicdata CoreMenuItemRelationships@>
parentId, id, loadOrder

Then you can add some additional information to the menu such as any flags/conditions on when it should be shown and any image to be displayed with it in the Trays view.

<@dynamicdata CoreMenuItemsFlags@>
id, flags

<@dynamicdata CoreMenuItemsImages@>
id, image, imageOpen
FUNCTIONA, ScsPageItem.gif,

To help get you started, I've posted a sample component that gives an example of these methods and includes a readme.html that goes into detail on the different options that are possible.

Thursday Jan 27, 2011

Handling URLs as content

[Read More]

Kyle Hatlestad is a Solution Architect in the WebCenter Architecture group (A-Team) who works with WebCenter Content and other products in the WebCenter & Fusion Middleware portfolios. The WebCenter A-Team blog can be found at: ateam_webcenter/


« July 2016